关于表变量是什么(和表变量不是什么),以及和临时表的比较让很多人非常困惑。虽然网上已经有了很多关于它们的文章,但我并没有发现一篇比较全面的。在本篇文章中,我们将探索表变量和临时表是什么(以及不是什么),然后我们通过使用临时表和表变量对其解密。
表变量
表变量在SQL Server 2000中首次被引入,那么,什么是表变量呢?微软在BOL (Declare @local_variable)中定义其为一个类型为表的变量。它的具体定义包括列定义,列名,数据类型和约束。而在表变量中可以使用的约束包括主键约束,唯一约束,Null约束和Check约束(外键约束不能在表变量中使用).定义表变量的语句是和正常使用Create table定义表语句的子集。只是表变量通过DECLARE @local_variable 语句进行定义。
通过参考1可以知道:
1)表变量拥有特定作用域(在当前批处理语句中,但不在任何当前批处理语句调用的存储过程和函数中),表变量在批处理结束后自动被清除。
2)参考6中在“Recompilations Due to Certain Temporary Table Operations” 环节讨论了临时表在会导致存储过程强制被重复编译的各种原因,但这些原因并不适用于表变量。表变量和临时表比起来会产生更少的存储过程重编译。
3)针对表变量的事务仅仅在更新数据时生效,所以锁和日志产生的数量会更少。
4)由于表变量的作用域如此之小,而且不属于数据库的持久部分,所以事务回滚不会影响表变量。
表变量可以在其作用域内像正常的表一样使用。更确切的说,表变量可以被当成正常的表或者表表达式一样在select,delete,update,insert语句中使用。但是表变量不能在类似“SELECT select_list INTO table_variable” 这样的语句中使用。而在SQL Server 2000中,表变量也不能被用于“INSERT INTO table_variable EXEC stored_procedure”这样的语句中。
表变量不能做如下事情:
1、虽然表变量是一个变量,但是其不能赋值给另一个变量。
2、check约束,默认值,和计算列不能引用自定义函数。
3、不能为约束命名。
4、不能Truncate表变量
5、不能向标识列中插入显式值(也就是说表变量不支持SET IDENTITY_INSERT ON)
临时表
在深入临时表之前,我们首先需要讨论一下会话(Session),一个会话仅仅是一个客户端到数据引擎的连接。在SQL Server Management Studio(SSMS)中,每一个查询窗口都会和数据库引擎建立连接。一个应用程序可以和数据库建立一个或多个连接,除此之外,应用程序还可能建立连接后一直不释放直到应用程序结束,也可能使用完释放连接需要时建立连接。
那么,什么是临时表?在BOL (CREATE TABLE)中,我们可以知道临时表和以Create table语句创建的表有着相同的物理构成,但临时表与正常的表不同之处有:
1)临时表的名字不能超过116个字符,这是由于数据库引擎为了辨别不同会话建立不同的临时表,所以会自动在临时表的名字后附加一串
2)局部临时表(以“#”开头命名的)作用域仅仅在当前的连接内,从在存储过程中建立局部临时表的角度来看,局部临时表会在下列情况被Drop:
a、显式调用DROP Table语句
b、当局部临时表在存储过程内被创建时,存储过程结束也就意味着局部临时表被DROP
c、当前会话结束,在会话内创建的所有局部临时表都会被Drop
3)全局临时表(以“##”开头命名的)在所有的会话内可见,所以在创建全局临时表之前首先检查其是否存在,否则如果已经存在,你将会得到重复创建对象的错误.
a、全局临时表会在创建其的会话结束后被DROP,其它会话将不能对全局临时表进行引用。
b、引用是在语句级别进行,比如说下面例子:
i、建立新的查询窗口,运行如下语句:
createtable##temp (RowIDint) |