在SQL Server中,临时表和表变量之间的区别是什么?

在SQL Server 2005中,有两种方法可以创建临时表:

declare @tmp table (Col1 int, Col2 int);

create table #tmp (Col1 int, Col2 int);

这两者之间有什么区别?关于@tmp是否仍然使用tempdb,或者是否所有事情都发生在内存中,我读过相互矛盾的意见。

在哪些情况下,一个会优于另一个?

401882 次浏览

@wcm -实际上nit选择表变量不只是Ram -它可以部分存储在磁盘上。

临时表可以有索引,而表变量只能有主索引。如果速度是一个问题,表变量可以更快,但显然如果有很多记录,或者需要搜索聚集索引的临时表,那么临时表将更好。

好的背景文章

对于所有相信临时变量只存在于内存中的人

首先,表变量不一定存在于内存中。在内存压力下,属于表变量的页可以被推到tempdb。

在这里阅读文章:表变量vs本地临时表

在哪些情况下,一个会优于另一个?

对于较小的表(小于1000行),使用临时变量,否则使用临时表。

临时表(#tmp)和表变量(@tmp)之间有一些区别,尽管使用tempdb不是其中之一,如下面MSDN链接中所述。

根据经验,对于中小数据量和简单的使用场景,应该使用表变量。(这是一个过于宽泛的指导方针,当然有很多例外-请参阅下面和下面的文章。)

在两者之间进行选择时需要考虑以下几点:

  • 临时表是真正的表,所以你可以做CREATE INDEXes等事情。如果您有大量的数据,通过索引访问这些数据会更快,那么临时表是一个很好的选择。

  • 表变量可以通过使用PRIMARY KEY或UNIQUE约束来拥有索引。(如果你想要一个非唯一的索引,只需将主键列作为唯一约束的最后一列。如果你没有唯一的列,你可以使用标识列)SQL 2014也有非唯一的索引

  • 表变量不参与事务,并且__abc0隐式地使用NOLOCK。事务行为可能非常有用,例如,如果你想在过程中途ROLLBACK,那么在该事务期间填充的表变量仍然会填充!

  • 临时表可能导致存储过程被重新编译,这种情况可能经常发生。表变量则不会。

  • 您可以使用SELECT INTO创建临时表,它可以更快地编写(适合临时查询),并且允许您随着时间的推移处理变化的数据类型,因为您不需要预先定义临时表结构。

  • 您可以从函数中传递表变量,使您能够更容易地封装和重用逻辑(例如,使一个函数将一个字符串分割成一个表的值在一些任意分隔符上)。

  • 在用户定义的函数中使用表变量可以更广泛地使用这些函数(详细信息请参阅CREATE FUNCTION文档)。如果你正在编写一个函数,你应该使用表变量而不是临时表,除非有迫切的需要。

  • 表变量和临时表都存储在tempdb中。但是表变量(自2005年以来)默认使用当前数据库的排序规则,而临时表则采用tempdb的默认排序规则(ref)。这意味着如果您使用临时表,并且您的db排序规则与tempdb的不同,则应该注意排序规则问题,如果您想比较临时表中的数据与数据库中的数据,则会导致问题。

  • 全局临时表(##tmp)是另一种类型的临时表,所有会话和用户都可以使用。

进一步阅读:

还要考虑到,您通常可以用派生表来替换这两个表,这也可能更快。但是,与所有性能调优一样,只有针对实际数据的实际测试才能告诉您特定查询的最佳方法。

另一个主要区别是表变量没有列统计信息,而临时表有。这意味着查询优化器不知道表变量中有多少行(它猜测是1),如果表变量实际上有大量行,这可能导致生成高度非优化的计划。

另一个区别:

表var只能从创建它的过程中的语句中访问,而不能从该过程调用的其他过程或嵌套的动态SQL(通过exec或sp_executesql)访问。

另一方面,临时表的作用域包括调用过程和嵌套动态SQL中的代码。

如果由过程创建的表必须可以从其他被调用的过程或动态SQL中访问,则必须使用临时表。这在复杂的情况下非常方便。

只要看看公认答案中的声明,即表变量不参与日志记录。

通常情况下,似乎不存在日志记录数量上的差异(至少对于对表本身的insert/update/delete操作,尽管我有自从发现,由于额外的系统表更新,存储过程中缓存的临时对象在这方面有一些小差异)。

在下面的操作中,我观察了@table_variable#temp表的日志记录行为。

  1. 成功的插入
  2. 多行插入语句因违反约束而回滚的位置。
  3. 更新
  4. 删除
  5. 释放

所有操作的事务日志记录几乎相同。

表变量版本实际上有一些额外的日志项,因为它将一个条目添加到(后来从sys.syssingleobjrefs基表中删除),但总体上记录的字节较少,因为表变量的内部名称比#temp表少消耗236个字节(少118个nvarchar字符)。

要重现的完整脚本(最好在单用户模式下启动并使用sqlcmd模式的实例上运行)

:setvar tablename "@T"
:setvar tablescript "DECLARE @T TABLE"


/*
--Uncomment this section to test a #temp table
:setvar tablename "#T"
:setvar tablescript "CREATE TABLE #T"
*/


USE tempdb
GO
CHECKPOINT


DECLARE @LSN NVARCHAR(25)


SELECT @LSN = MAX([Current LSN])
FROM fn_dblog(null, null)




EXEC(N'BEGIN TRAN StartBatch
SAVE TRAN StartBatch
COMMIT


$(tablescript)
(
[4CA996AC-C7E1-48B5-B48A-E721E7A435F0] INT PRIMARY KEY DEFAULT 0,
InRowFiller char(7000) DEFAULT ''A'',
OffRowFiller varchar(8000) DEFAULT REPLICATE(''B'',8000),
LOBFiller varchar(max) DEFAULT REPLICATE(cast(''C'' as varchar(max)),10000)
)




BEGIN TRAN InsertFirstRow
SAVE TRAN InsertFirstRow
COMMIT


INSERT INTO $(tablename)
DEFAULT VALUES


BEGIN TRAN Insert9Rows
SAVE TRAN Insert9Rows
COMMIT




INSERT INTO $(tablename) ([4CA996AC-C7E1-48B5-B48A-E721E7A435F0])
SELECT TOP 9 ROW_NUMBER() OVER (ORDER BY (SELECT 0))
FROM sys.all_columns


BEGIN TRAN InsertFailure
SAVE TRAN InsertFailure
COMMIT




/*Try and Insert 10 rows, the 10th one will cause a constraint violation*/
BEGIN TRY
INSERT INTO $(tablename) ([4CA996AC-C7E1-48B5-B48A-E721E7A435F0])
SELECT TOP (10) (10 + ROW_NUMBER() OVER (ORDER BY (SELECT 0))) % 20
FROM sys.all_columns
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE()
END CATCH


BEGIN TRAN Update10Rows
SAVE TRAN Update10Rows
COMMIT


UPDATE $(tablename)
SET InRowFiller = LOWER(InRowFiller),
OffRowFiller  =LOWER(OffRowFiller),
LOBFiller  =LOWER(LOBFiller)




BEGIN TRAN Delete10Rows
SAVE TRAN Delete10Rows
COMMIT


DELETE FROM  $(tablename)
BEGIN TRAN AfterDelete
SAVE TRAN AfterDelete
COMMIT


BEGIN TRAN EndBatch
SAVE TRAN EndBatch
COMMIT')




DECLARE @LSN_HEX NVARCHAR(25) =
CAST(CAST(CONVERT(varbinary,SUBSTRING(@LSN, 1, 8),2) AS INT) AS VARCHAR) + ':' +
CAST(CAST(CONVERT(varbinary,SUBSTRING(@LSN, 10, 8),2) AS INT) AS VARCHAR) + ':' +
CAST(CAST(CONVERT(varbinary,SUBSTRING(@LSN, 19, 4),2) AS INT) AS VARCHAR)


SELECT
[Operation],
[Context],
[AllocUnitName],
[Transaction Name],
[Description]
FROM   fn_dblog(@LSN_HEX, null) AS D
WHERE  [Current LSN] > @LSN


SELECT CASE
WHEN GROUPING(Operation) = 1 THEN 'Total'
ELSE Operation
END AS Operation,
Context,
AllocUnitName,
COALESCE(SUM([Log Record Length]), 0) AS [Size in Bytes],
COUNT(*)                              AS Cnt
FROM   fn_dblog(@LSN_HEX, null) AS D
WHERE  [Current LSN] > @LSN
GROUP BY GROUPING SETS((Operation, Context, AllocUnitName),())

结果

+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+
|                       |                    |                           |             @TV      |             #TV      |                  |
+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+
| Operation             | Context            | AllocUnitName             | Size in Bytes | Cnt  | Size in Bytes | Cnt  | Difference Bytes |
+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+
| LOP_ABORT_XACT        | LCX_NULL           |                           | 52            | 1    | 52            | 1    |                  |
| LOP_BEGIN_XACT        | LCX_NULL           |                           | 6056          | 50   | 6056          | 50   |                  |
| LOP_COMMIT_XACT       | LCX_NULL           |                           | 2548          | 49   | 2548          | 49   |                  |
| LOP_COUNT_DELTA       | LCX_CLUSTERED      | sys.sysallocunits.clust   | 624           | 3    | 624           | 3    |                  |
| LOP_COUNT_DELTA       | LCX_CLUSTERED      | sys.sysrowsets.clust      | 208           | 1    | 208           | 1    |                  |
| LOP_COUNT_DELTA       | LCX_CLUSTERED      | sys.sysrscols.clst        | 832           | 4    | 832           | 4    |                  |
| LOP_CREATE_ALLOCCHAIN | LCX_NULL           |                           | 120           | 3    | 120           | 3    |                  |
| LOP_DELETE_ROWS       | LCX_INDEX_INTERIOR | Unknown Alloc Unit        | 720           | 9    | 720           | 9    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysallocunits.clust   | 444           | 3    | 444           | 3    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysallocunits.nc      | 276           | 3    | 276           | 3    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.syscolpars.clst       | 628           | 4    | 628           | 4    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.syscolpars.nc         | 484           | 4    | 484           | 4    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysidxstats.clst      | 176           | 1    | 176           | 1    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysidxstats.nc        | 144           | 1    | 144           | 1    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysiscols.clst        | 100           | 1    | 100           | 1    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysiscols.nc1         | 88            | 1    | 88            | 1    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysobjvalues.clst     | 596           | 5    | 596           | 5    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysrowsets.clust      | 132           | 1    | 132           | 1    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysrscols.clst        | 528           | 4    | 528           | 4    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysschobjs.clst       | 1040          | 6    | 1276          | 6    | 236              |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysschobjs.nc1        | 820           | 6    | 1060          | 6    | 240              |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysschobjs.nc2        | 820           | 6    | 1060          | 6    | 240              |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.sysschobjs.nc3        | 480           | 6    | 480           | 6    |                  |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.syssingleobjrefs.clst | 96            | 1    |               |      | -96              |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | sys.syssingleobjrefs.nc1  | 88            | 1    |               |      | -88              |
| LOP_DELETE_ROWS       | LCX_MARK_AS_GHOST  | Unknown Alloc Unit        | 72092         | 19   | 72092         | 19   |                  |
| LOP_DELETE_ROWS       | LCX_TEXT_MIX       | Unknown Alloc Unit        | 16348         | 37   | 16348         | 37   |                  |
| LOP_FORMAT_PAGE       | LCX_HEAP           | Unknown Alloc Unit        | 1596          | 19   | 1596          | 19   |                  |
| LOP_FORMAT_PAGE       | LCX_IAM            | Unknown Alloc Unit        | 252           | 3    | 252           | 3    |                  |
| LOP_FORMAT_PAGE       | LCX_INDEX_INTERIOR | Unknown Alloc Unit        | 84            | 1    | 84            | 1    |                  |
| LOP_FORMAT_PAGE       | LCX_TEXT_MIX       | Unknown Alloc Unit        | 4788          | 57   | 4788          | 57   |                  |
| LOP_HOBT_DDL          | LCX_NULL           |                           | 108           | 3    | 108           | 3    |                  |
| LOP_HOBT_DELTA        | LCX_NULL           |                           | 9600          | 150  | 9600          | 150  |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysallocunits.clust   | 456           | 3    | 456           | 3    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.syscolpars.clst       | 644           | 4    | 644           | 4    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysidxstats.clst      | 180           | 1    | 180           | 1    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysiscols.clst        | 104           | 1    | 104           | 1    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysobjvalues.clst     | 616           | 5    | 616           | 5    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysrowsets.clust      | 136           | 1    | 136           | 1    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysrscols.clst        | 544           | 4    | 544           | 4    |                  |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.sysschobjs.clst       | 1064          | 6    | 1300          | 6    | 236              |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | sys.syssingleobjrefs.clst | 100           | 1    |               |      | -100             |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | Unknown Alloc Unit        | 135888        | 19   | 135888        | 19   |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_INTERIOR | Unknown Alloc Unit        | 1596          | 19   | 1596          | 19   |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysallocunits.nc      | 288           | 3    | 288           | 3    |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.syscolpars.nc         | 500           | 4    | 500           | 4    |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysidxstats.nc        | 148           | 1    | 148           | 1    |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysiscols.nc1         | 92            | 1    | 92            | 1    |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysschobjs.nc1        | 844           | 6    | 1084          | 6    | 240              |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysschobjs.nc2        | 844           | 6    | 1084          | 6    | 240              |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.sysschobjs.nc3        | 504           | 6    | 504           | 6    |                  |
| LOP_INSERT_ROWS       | LCX_INDEX_LEAF     | sys.syssingleobjrefs.nc1  | 92            | 1    |               |      | -92              |
| LOP_INSERT_ROWS       | LCX_TEXT_MIX       | Unknown Alloc Unit        | 5112          | 71   | 5112          | 71   |                  |
| LOP_MARK_SAVEPOINT    | LCX_NULL           |                           | 508           | 8    | 508           | 8    |                  |
| LOP_MODIFY_COLUMNS    | LCX_CLUSTERED      | Unknown Alloc Unit        | 1560          | 10   | 1560          | 10   |                  |
| LOP_MODIFY_HEADER     | LCX_HEAP           | Unknown Alloc Unit        | 3780          | 45   | 3780          | 45   |                  |
| LOP_MODIFY_ROW        | LCX_CLUSTERED      | sys.syscolpars.clst       | 384           | 4    | 384           | 4    |                  |
| LOP_MODIFY_ROW        | LCX_CLUSTERED      | sys.sysidxstats.clst      | 100           | 1    | 100           | 1    |                  |
| LOP_MODIFY_ROW        | LCX_CLUSTERED      | sys.sysrowsets.clust      | 92            | 1    | 92            | 1    |                  |
| LOP_MODIFY_ROW        | LCX_CLUSTERED      | sys.sysschobjs.clst       | 1144          | 13   | 1144          | 13   |                  |
| LOP_MODIFY_ROW        | LCX_IAM            | Unknown Alloc Unit        | 4224          | 48   | 4224          | 48   |                  |
| LOP_MODIFY_ROW        | LCX_PFS            | Unknown Alloc Unit        | 13632         | 169  | 13632         | 169  |                  |
| LOP_MODIFY_ROW        | LCX_TEXT_MIX       | Unknown Alloc Unit        | 108640        | 120  | 108640        | 120  |                  |
| LOP_ROOT_CHANGE       | LCX_CLUSTERED      | sys.sysallocunits.clust   | 960           | 10   | 960           | 10   |                  |
| LOP_SET_BITS          | LCX_GAM            | Unknown Alloc Unit        | 1200          | 20   | 1200          | 20   |                  |
| LOP_SET_BITS          | LCX_IAM            | Unknown Alloc Unit        | 1080          | 18   | 1080          | 18   |                  |
| LOP_SET_BITS          | LCX_SGAM           | Unknown Alloc Unit        | 120           | 2    | 120           | 2    |                  |
| LOP_SHRINK_NOOP       | LCX_NULL           |                           |               |      | 32            | 1    | 32               |
+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+
| Total                 |                    |                           | 410144        | 1095 | 411232        | 1092 | 1088             |
+-----------------------+--------------------+---------------------------+---------------+------+---------------+------+------------------+
  1. Temp表:Temp表便于创建和备份数据。

    表变量:但是表变量涉及到我们通常创建普通表时的工作。

  2. Temp table: Temp table结果可被多个用户使用。

    表变量:但表变量只能被当前用户使用。

  3. Temp table: Temp table将存储在tempdb中。这会造成网络流量。当临时表中有大量数据时,它必须跨数据库工作。性能问题将会存在。

    表变量:但是表变量将存储在物理内存中的一些数据,然后当大小增加时,它将被移动到tempdb。

  4. Temp table: Temp table可以执行DDL的所有操作。它允许创建索引,删除,更改等。

    表变量:而表变量不允许执行DDL操作。但是表变量只允许我们创建聚集索引。

  5. 临时表:临时表可以用于当前会话,也可以用于全局。这样多用户会话就可以利用表中的结果。

    表变量:但是表变量可以在该程序中使用。(存储过程)

  6. 临时表:临时变量不能使用事务。当我们对临时表执行DML操作时,可以回滚或提交事务。

    表变量:但是我们不能对表变量这样做。

  7. Temp表:函数不能使用Temp变量。此外,我们不能在函数中进行DML操作。

    表变量:但是函数允许我们使用表变量。但是使用表格变量我们可以做到这一点。

  8. Temp表:当我们对每个后续调用都使用Temp变量时,存储过程将进行重新编译(不能使用相同的执行计划)。

    Table变量:而Table变量不会这样做。

引用自;专业SQL Server 2012内部和故障处理

< >强统计 临时表和表变量之间的主要区别是 统计信息不是在表变量上创建的。这主要有两个方面 结果,第一个是查询优化器使用 修正了对表变量中行数的估计 不管它包含什么数据。此外,添加或删除

索引不能在表变量上创建索引,尽管可以 创建约束。这意味着通过创建主键或唯一键 约束,您可以有索引(因为这些是创建来支持的 约束)在表变量上。即使你有限制,而且 因此,索引将有统计信息,索引将没有 在编译查询时使用,因为它们在编译时不存在 时间,也不会导致重新编译

模式的修改模式修改可以临时 表,而不是表变量。尽管模式修改是 可能在临时表上,避免使用它们,因为它们会导致 使用表的语句的重新编译

临时表与表变量

表变量不是在内存中创建的

有一种常见的误解,认为表变量是内存中的结构 这样会比临时表执行得更快。多亏了车管所 叫做sys。“Dm _ db _ session _ space _ usage”,显示tempdb的使用情况 会话,你可以证明事实并非如此。重新启动SQL Server后清除 DMV,运行以下脚本确认您的session _ id返回0 User _ objects _ alloc _ page _ count:

. bb0
SELECT session_id,
database_id,
user_objects_alloc_page_count
FROM sys.dm_db_session_space_usage
WHERE session_id > 50 ;

现在您可以通过运行以下命令检查临时表使用了多少空间 脚本创建一个只有一列的临时表,并用一行填充它

CREATE TABLE #TempTable ( ID INT ) ;
INSERT INTO #TempTable ( ID )
VALUES ( 1 ) ;
GO
SELECT session_id,
database_id,
user_objects_alloc_page_count
FROM sys.dm_db_session_space_usage
WHERE session_id > 50 ;
我的服务器上的结果表明该表在tempdb中分配了一个页面。 现在运行相同的脚本,但是使用一个表变量 这一次:< / p >
DECLARE @TempTable TABLE ( ID INT ) ;
INSERT INTO @TempTable ( ID )
VALUES ( 1 ) ;
GO
SELECT session_id,
database_id,
user_objects_alloc_page_count
FROM sys.dm_db_session_space_usage
WHERE session_id > 50 ;

用哪一个?

是否使用临时表或表变量应该 由彻底的测试决定,但最好倾向于临时的 表作为默认值,因为可以删除的东西要少得多 错了> < /强。

我曾经见过客户使用表变量开发代码,因为他们 我们处理的是少量的行,它比 临时的桌子,但几年后就有了几百家 表中有数千行变量,性能很糟糕, 所以当你做你的 决定!< / p >

Temporary Tables (##temp/#temp)Table Variables (@table)的区别如下:

  1. Table variable (@table)是在memory. xml中创建的。然而,Temporary table (##temp/#temp)是在tempdb database. xml中创建的。然而,如果存在内存压力,属于表变量的页面可能会被推到tempdb。

  2. Table variables不能参与transactions, logging or locking。这使得@table faster then #temp。所以变量表比临时表快。

  3. Temporary table允许不同于Table variables的模式修改。

  4. Temporary tables在创建的例程和子例程中可见。而Table变量只在创建的例程中可见。

  5. Temporary tables被允许使用CREATE INDEXes,而Table variables不被允许使用CREATE INDEX,相反,它们可以使用Primary Key or Unique Constraint有索引。

令我惊讶的是,没有人提到这两者之间的关键区别是临时表支持平行插入,而表变量不支持。您应该能够从执行计划中看出不同之处。这里是第9频道的SQL workshop视频MSDN文档

这也解释了为什么对于较小的表应该使用表变量,否则使用临时表,如前面的SQLMenace回答

在SQL中,临时表存储在TempDB中,本地临时表只在当前会话中可见,在另一个会话中不可见。这可以在嵌套存储过程调用之间共享。全局临时表对所有其他会话可见,当最后一个连接引用表关闭时,它们将被销毁。例如,

Select Dept.DeptName, Dept.DeptId, COUNT(*) as TotalEmployees
into #TempEmpCount
from Tbl_EmpDetails Emp
join Tbl_Dept Dept
on Emp.DeptId = Dept.DeptId
group by DeptName, Dept.DeptId

表变量类似于tempTables,表变量也是在TempDB中创建的。表变量的作用域是声明表变量的批处理、存储过程或语句块。它们可以作为过程之间的参数传递。同样的查询可以使用Table变量by来编写

Declare @tblEmployeeCount table
(DeptName nvarchar(20),DeptId int, TotalEmployees int)
Insert @tblEmployeeCount
Select DeptName, Tbl_Dept.DeptId, COUNT(*) as TotalEmployees
from Tbl_EmpDetails
join Tbl_Dept
on Tbl_EmpDetails.DeptId = Tbl_Dept.DeptId
group by DeptName, Tbl_Dept.DeptId