create table #temptable 临时表 和 declare @bianliang table ()表变量

在开发过程中,经常会遇到使用表变量和本地临时表的情况。下面是对二者的一个介绍:

1. 为什么要使用表变量

表变量是从2000开始引入的,微软认为与本地临时表相比,表变量具有如下优点:
  a.与其他变量的定义一样,表变量具有良好的定义范围,并会被自动清除;
  b.在存储过程中使用表变量会减少存储过程重新编译的发生;
  c.表变量需要更少的锁请求和日志资源;
  d.可以在表变量上使用UDF,UDDT,XML。

2.表变量的限制

与临时表相比,表变量存在着如下缺点:
  a.在表变量上没有统计信息,查询优化器根据固定的预估值来选择执行计划,在数据很多的情况下,会导致查询优化器选择很差的执行计划;
  b.不能直接在表变量上创建索引,但可以通过创建约束(主键、唯一)来建立索引;
  c.在DECLARE后,不能再对表变量进行更改;
  d.不能对表变量执行INSERT EXEC,SELECT INTO语句;
  e.不能通过EXEC或sp_executesql来执行牵涉到表变量的动态SQL语句,但如果表变量是在动态SQL语句内定义的,则可以。

3.那什么时候可以使用表变量

要使用表变量应该根据如下规则来判断:
  a.表的行数;
  b.使用表变量能够减少的重新编译次数;
  c.查询的类型和对索引或者统计信息的依赖程度;
  d.需要生用UDF,UDDT,XML的时候。
其实也就说,得从实际出发,根据具体的查询,作出具体的选择。但是,其中很关键的一点,如果表的行数非常多,使用表变量其实是更费资源的。有人提出了这样的建议:对于行数较少的情况下(小于1000行)可以使用表变量;如果行数很多(有几万行),则使用临时表。

因此,在实际的开发中,应通过分别使用临时表或表变量进行对比后,才作出决定。

下面是一个例子,插入临时表和表变量的数据有20多万行,可以看到,使用临时表的时间是使用表变量所花时间的1/5。

表 'SalesOrderHeader'。扫描计数 3,逻辑读取 130 次,物理读取 9 次,预读 43 次,lob 逻辑读取 0 次,lob 物理读取 0次,lob 预读 0 次。
表 '#SalesOrderDetail___________________________________________________________________________________________________00000000001F'。扫描计数 3,逻辑读取 12331 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0次,lob 物理读取 0 次,lob 预读 0 次。
表 'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

SQL Server 执行时间:
   CPU 时间 = 2281 毫秒,占用时间 = 19726 毫秒。
select with temporary table: 20140 ms

********************************************************************************

表 'SalesOrderHeader'。扫描计数 0,逻辑读取 764850 次,物理读取 17 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 '#4E88ABD4'。扫描计数 1,逻辑读取 12331 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0次,lob 预读 0 次。

SQL Server 执行时间:
   CPU 时间 = 4375 毫秒,占用时间 = 107160 毫秒。
select with table variable: 107160 ms

4.使用表变量的误区

对于表变量,很多人认为,表变量和其他变量一样,只存在内存中,其实这是不正确的,表变量也存在tempdb中。可以通过下面例子进行对比。

CREATE TABLE #TempTable (TT_Col1 INT)

DECLARE @TableVariable TABLE (TV_Col1 INT)

SELECT TOP 2 *

FROM tempdb.sys.objects

ORDER BY create_date DESC

name
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#03317E3D
#TempTable__________________________________________________________________________________________________________000000000003

#03317E3D就是刚创建的表变量;

5.其他

表变量不受rollback影响,某些情况下会破坏数据的完整性。

CREATE TABLE #TempTable (TT_Col1 INT)
DECLARE @TableVariable TABLE (TV_Col1 INT)
INSERT #TempTable VALUES (1)
INSERT @TableVariable VALUES (1)
BEGIN TRANSACTION
     INSERT #TempTable VALUES (2)
      INSERT @TableVariable VALUES (2)
ROLLBACK
SELECT * FROM #TempTable

/*
TT_Col1
-------
1
*/

SELECT * FROM @TableVariable
--返回了两条记录
/*
TV_Col1
-------
1
2
*/

6.参考

http://support.microsoft.com/default.aspx?scid=kb;en-us;305977&Product=sql2k
www.sqlservercentral.com/articles/63472/databases.aspfaq.com/database/should-i-use-a-temp-table-or-a-table-variable.html
www.sqlservercentral.com/articles/Temporary+Tables/66720/

 
分类: 数据库
 
 
 

Sqlserver 实际开发中表变量的用法

Sqlserver 实际开发中表变量的用法

 

在实际的开发中,我们可能遇到的问题是,在一个存储过程里面,我们可能要返回多段sql的结果集,但是最终怎么把多个结果集合成一块呢,那么这个时候临时表变量就来了

declare  @tmp table   --声明表变量
(
id int identity(1,1),    --字段 必须和插入表变量里的数量一一对应
Name varchar(60),
[Description] varchar(60),
Category varchar(60)
)
insert @tmp
     select Book.Name,Book.[Description],Book.Category from Book
select * from  @tmp

这是正常的sql写法,注意的是: select 到from中间的字段一定要和表变量里的字段一样,顺序,数量一一对应

下面是存储过程的写法:

create  proc P_getSelect
as
begin
declare  @tmp table  --声明表变量
(
id int identity(1,1),
Name varchar(60),
[Description] varchar(60),
Category varchar(60)
)
insert @tmp
     select Book.Name,Book.[Description],Book.Category from Book

declare  @tmp2 table
(
id int identity(1,1),
Name varchar(60),
[Description] varchar(60),
Category varchar(60)
)
insert @tmp2     --声明表变量2   这里为了方便  我把一个表的数据分别放到两个表变量里了
     select Book.Name,Book.[Description],Book.Category from Book
     select t.*,tt.* from @tmp t ,@tmp2 tt

end

exec P_getSelect

最新文章

  1. Mac安装windows虚拟机攻略
  2. [AngularJS] Using $anchorScroll
  3. PHP ini_set() 函数
  4. 从IT的角度思考BIM(二):模式与框架
  5. Java 中 StringBuilder 在高性能用法总结
  6. DNA repair - HDU 2457(自动机+dp)
  7. R语言画正弦曲线
  8. osgText::Text简介
  9. linux tar解压命令
  10. docker~不使用yml批量部署服务
  11. Javascript 3.2
  12. Python *Mix_w5
  13. LeetCode(31): 下一个排列
  14. SpringBoot配置多数据源时遇到的问题
  15. lch 儿童围棋课堂 启蒙篇 (李昌镐 著)
  16. SANS社区帐号邮件激活问题
  17. 如何让IE7,IE8支持css3
  18. php:生成的时间与本地电脑的时间不匹配
  19. base64加密PHP脚本的解码方法
  20. mybatis传递多个参数值(转)

热门文章

  1. PHP中利用PHPMailer使用QQ邮箱实现邮件发送
  2. asp.net core 身份认证/权限管理系统简介及简单案例
  3. POJ 1298 The Hardest Problem Ever【字符串】
  4. Python的并发并行[1] -> 线程[2] -> 锁与信号量
  5. POJ 1741 Tree 树的分治
  6. [BZOJ 2957]楼房重建(THU2013集训)(线段树维护单调栈)
  7. Linux下进行Web服务器压力(并发)测试工具http_load、webbench、ab、Siege、autobench简单使用教程(转)
  8. Lazy Scheduler:我的轻量级任务调度框架
  9. zookeeper 学习笔记2
  10. CSS3:2D转换方法