表变量和临时表详解

首先让我们来看看什么是表变量和临时表。

sql server 表变量

1.初识表变量
  表变量在sql server 2000中首次被引用。表变量的定义和创建一个表大致相同,只不过是使用DECLARE @variable而不是CREATE Table,表变量定义包括列定义,列名,数据类型和约束(可用的约束有:主键约束、唯一约束、null约束、和CHECK约束。注:外键约束不可以哦)。表变量和其他变量不同,它不止存在于内存中,还存在于tempdb中。

2.表变量优点
  1).表变量拥有特定的作用域(在当前批处理中),表变量在批处理结束后自动被清除。
  2).在存储过程中使用表变量较临时表会减少存储过程重新编译的发生。
  3).表变量需要更少的锁请求和日志资源。
  4).可以在表变量上使用UDF,UDDT,XML

3.表变量的缺点
  1).在表变量上没有统计信息,查询优化器根据固定的预估值来选择执行计划,在数据量很大的情况下,会导致查询优化器选择很差的执行计划。
  2).不能在表变量上创建索引,但是可以通过创建约束(主键、唯一)来建立索引;
  3).在 DECLARE 之后,不能再对表变量进行更改;
  4).不能对表变量使用 SELECT INTO,INSERT EXEC 语句;
  5).不能通过EXEC或sp_executeSQL 来执行牵涉表变量的动态SQL语句,但如果表变量是在动态SQL语句内定义的,则可以。

4.何时使用表变量(可以根据以下规则来判断何时使用表变量)
  1).表的行数
  2).使用表变量能够减少的重新编译次数
  3).查询的类型和对索引或者统计信息的依赖程度
  4).是否需要使用UDF,UDDF,XML

5.表变量不能做的事
  1).虽然表变量是一个变量,但是其不能赋值给另一个变量。
  2).check约束、默认值、计算列不能引用自定义函数。
  3).不能为约束命名
  4).不能truncate 表变量
  5).不能向标识列中插入显示值(也就是说表变量不支持SET IDENTITY_INSERT ON)

 

sql server 临时表

临时表和Create Table语句创建的表的不同之处在于:
  1).临时表的名称不能超过116个字符,这是由于数据库引擎为了辨别不同会话建立的临时表,会自动在临时表名字后附加一串。
  2).局部临时表作用域仅仅在当前的连接内,从存储过程中建立局部临时表的角度来看,局部临时表会在以下情况下别Drop:
    a.显示调用DROP TABLE语句
    b.当局部临时表在存储过程内被创建时,存储过程结束就意味着局部临时表被Drop
    c.当前会话结束,在会话内创建的所有局部临时表都会被DROP。
  3).全局临时表在所有的会话内可见,但是在其创建的会话结束后即被drop,drop后其它会话也将不能对其进行引用。
  4).不能对临时表进行分区。
  5).不能对临时表加外键约束。
  6).临时表内列的数据类型不能定义成没有在TempDb中没有定义自定义数据类型(自定义数据类型是数据库级别的对象,而临时表属于TempDb)。由于TempDb在每次SQL   Server重启后会被自动创建,所以你必须使用startup stored procedure来为TempDb创建自定义数据类型。你也可以通过修改Model数据库来达到这一目标。
  7).XML列不能定义成XML集合的形式,除非这个集合已经在TempDb中定义。

 

  至于表变量和临时表的区别,在介绍表变量时所提到的优缺点中基本概括了,另外还有一个区别是体现在排序规则上:表变量使用当前数据库的排序规则,临时表使用TempDb的排序规则。如果它们不兼容,你还需要在查询或者表定义中进行指定。

  下面是看到的别人整理的一张表格,看着清晰一点。

总结

 

特性 表变量 临时表
作用域 当前批处理 当前会话,嵌套存储过程,全局:所有会话
使用场景 自定义函数,存储过程,批处理 自定义函数,存储过程,批处理
创建方式 DECLARE statement only.只能通过DECLEARE语句创建

CREATE TABLE 语句

SELECT INTO 语句.

表名长度 最多128字节 最多116字节
列类型

可以使用自定义数据类型

可以使用XML集合

自定义数据类型和XML集合必须在TempDb内定义
Collation 字符串排序规则继承自当前数据库 字符串排序规则继承自TempDb数据库
索引 索引必须在表定义时建立 索引可以在表创建后建立
约束 PRIMARY KEY, UNIQUE, NULL, CHECK约束可以使用,但必须在表建立时声明 PRIMARY KEY, UNIQUE, NULL, CHECK. 约束可以使用,可以在任何时后添加,但不能有外键约束
表建立后使用DDL (索引,列) 不允许 允许.
数据插入方式 INSERT 语句 (SQL 2000: 不能使用INSERT/EXEC).

INSERT 语句, 包括 INSERT/EXEC.

SELECT INTO 语句.

Insert explicit values into identity columns (SET IDENTITY_INSERT). 不支持SET IDENTITY_INSERT语句 支持SET IDENTITY_INSERT语句
Truncate table 不允许 允许
析构方式 批处理结束后自动析构 显式调用 DROP TABLE 语句. 
当前会话结束自动析构 (全局临时表: 还包括当其它会话语句不在引用表.)
事务 只会在更新表的时候有事务,持续时间比临时表短 正常的事务长度,比表变量长
存储过程重编译 会导致重编译
回滚 不会被回滚影响 会被回滚影响
统计数据 不创建统计数据,所以所有的估计行数都为1,所以生成执行计划会不精准 创建统计数据,通过实际的行数生成执行计划。
作为参数传入存储过程 仅仅在SQL Server2008, 并且必须预定义 user-defined table type. 不允许
显式命名对象 (索引, 约束). 不允许 允许,但是要注意多用户的问题
动态SQL 必须在动态SQL中定义表变量 可以在调用动态SQL之前定义临时表

posted @ 2016-05-06 09:27  Jiang_Xi  阅读(839)  评论(0编辑  收藏  举报