`

SQL Server中临时表与表变量的区别

阅读更多

我们在数据库中使用表的时候,经常会遇到两种使用表的方法,分别就是使用临时表及表变量。在实际使用的时候,我们如何灵活的在存储过程中运用它们,虽然它们实现的功能基本上是一样的,可如何在一个存储过程中有时候去使用临时表而不使用表变量,有时候去使用表变量而不使用临时表呢?

  临时表

  临时表与永久表相似,只是它的创建是在Tempdb中,它只有在一个数据库连接结束后或者由SQL命令DROP掉,才会消失,否则就会一直存在。临时表在创建的时候都会产生SQL Server的系统日志,虽它们在Tempdb中体现,是分配在内存中的,它们也支持物理的磁盘,但用户在指定的磁盘里看不到文件。

  临时表分为本地和全局两种,本地临时表的名称都是以“#”为前缀,只有在本地当前的用户连接中才是可见的,当用户从实例断开连接时被删除。全局临时表的名称都是以“##”为前缀,创建后对任何用户都是可见的,当所有引用该表的用户断开连接时被删除。

  下面我们来看一个创建临时表的例子:

      

      CREATE TABLE dbo.#News 
  ( 
  News_id int NOT NULL, 
  NewsTitle varchar(100), 
  NewsContent varchar(2000), 
  NewsDateTime datetime 
  )

      临时表可以创建索引,也可以定义统计数据,所以可以用数据定义语言(DDL)的声明来阻止临时表添加的限制,约束,并参照完整性,如主键和外键约束。比如来说,我们现在来为#News表字段NewsDateTime来添加一个默认的GetData()当前日期值,并且为News_id添加一个主键,我们就可以使用下面的语句:

    

      ALTER TABLE dbo.#News 
  ADD 
  CONSTRAINT [DF_NewsDateTime] DEFAULT (GETDATE()) FOR [NewsDateTime], 
  PRIMARY KEY CLUSTERED 
  ( 
  [News_id] 
  ) ON [PRIMARY] 
  GO

    临时表在创建之后可以修改许多已定义的选项,包括:

  1)添加、修改、删除列。例如,列的名称、长度、数据类型、精度、小数位数以及为空性均可进行修改,只是有一些限制而已。

  2)可添加或删除主键和外键约束。

  3)可添加或删除 UNIQUE 和 CHECK 约束及 DEFAULT 定义(对象)。

  4)可使用 IDENTITY 或 ROWGUIDCOL 属性添加或删除标识符列。虽然 ROWGUIDCOL 属性也可添加至现有列或从现有列删除,但是任何时候在表中只能有一列可具有该属性

5)表及表中所选定的列已注册为全文索引。

  表变量

  表变量创建的语法类似于临时表,区别就在于创建的时候,必须要为之命名。表变量是变量的一种,表变量也分为本地及全局的两种,本地表变量的名称都是以“@”为前缀,只有在本地当前的用户连接中才可以访问。全局的表变量的名称都是以“@@”为前缀,一般都是系统的全局变量,像我们常用到的,如@@Error代表错误的号,@@RowCount代表影响的行数。

  如我们看看创建表变量的语句:

     

      DECLARE @News Table 
  ( 
  News_id int NOT NULL, 
  NewsTitle varchar(100), 
  NewsContent varchar(2000), 
  NewsDateTime datetime 
  )

   比较临时表及表变量都可以通过SQL的选择、插入、更新及删除语句,它们的的不同主要体现在以下这些:

  1)表变量是存储在内存中的,当用户在访问表变量的时候,SQL Server是不产生日志的,而在临时表中是产生日志的;

  2)在表变量中,是不允许有非聚集索引的;

  3)表变量是不允许有DEFAULT默认值,也不允许有约束;

  4)临时表上的统计信息是健全而可靠的,但是表变量上的统计信息是不可靠的;

  5)临时表中是有锁的机制,而表变量中就没有锁的机制。

  我们现在来看一个完整的例子,来看它们的用法的异同:

  利用临时表  

      

      CREATE TABLE dbo.#News 
  ( 
  News_id int NOT NULL, 
  NewsTitle varchar(100), 
  NewsContent varchar(2000), 
  NewsDateTime datetime 
  ) 
  INSERT INTO dbo.#News (News_id, NewsTitle, NewsContent, NewsDateTime) 
  VALUES (1,'BlueGreen', 'Austen', 200801, GETDATE()) 
  SELECT News_id, NewsTitle, NewsContent, NewsDateTime FROM dbo.#News 
  DROP TABLE dbo.[#News]

    利用表变量

 

DECLARE @News table 
  ( 
  News_id int NOT NULL, 
  NewsTitle varchar(100), 
  NewsContent varchar(2000), 
  NewsDateTime datetime 
  ) 
  INSERT INTO @News (News_id, NewsTitle, NewsContent, NewsDateTime) 
  VALUES (1,'BlueGreen', 'Austen', 200801, GETDATE()) 
  SELECT News_id, NewsTitle, NewsContent, NewsDateTime FROM @News

 我们可以看到上面两种情况实现的是一样的效果,第一种利用临时表的时候,临时表一般被创建后,如果在执行的时候,没有通过DROP Table的操作,第二次就不能再被创建,而定义表变量也不需要进行DROP Table的操作,一次执行完成后就会消失。

  其实在选择临时表还是表变量的时候,我们大多数情况下在使用的时候都是可以的,但一般我们需要遵循下面这个情况,选择对应的方式:

  1)使用表变量主要需要考虑的就是应用程序对内存的压力,如果代码的运行实例很多,就要特别注意内存变量对内存的消耗。我们对于较小的数据或者是通过计算出来的推荐使用表变量。如果数据的结果比较大,在代码中用于临时计算,在选取的时候没有什么分组的聚合,就可以考虑使用表变量。

  2)一般对于大的数据结果,或者因为统计出来的数据为了便于更好的优化,我们就推荐使用临时表,同时还可以创建索引,由于临时表是存放在Tempdb中,一般默认分配的空间很少,需要对tempdb进行调优,增大其存储的空间。

补充:
      1.使事务日志不会记录表变量。因此,它们脱离了事务机制的范围。

      2.任何一个使用临时表的存储过程都不会被预编译,然而使用表变量的存储过程的执行计划可以预先静态的编译。预编译一个脚本的主要好处在于加快了执行的速度。这个好处对于长的存储过程更加显著,因为对它来说重新编译代价太高。

      3.表变量仅存在于那些变量能存在的相同范围内。和临时表相反,它们在内部存储过程和execstring)语句里是不可见的。它们也不能在insert/exec语句里使用。

 

问题 1:为什么在已经有了临时表的情况下还要引入表变量?

解答 1:
与临时表相比,表变量具有下列优点:

如 SQL Server 联机丛书“表”(Table) 一文中所述,表变量(如局部变量)具有明确定义的范围,在该范围结束时会自动清除这些表变量。
与临时表相比,表变量导致存储过程的重新编译更少。
涉及表变量的事务仅维持表变量上更新的持续时间。因此,使用表变量时,需要锁定和记录资源的情况更少。因为表变量具有有限的范围并且不是持久性数据库的一部分,所以事务回滚并不影响它们。
问题 2:如果说使用表变量比使用临时表导致存储过程的重新编译更少,这意味着什么?

解答 2:下面的文章讨论了重新编译存储过程的一些原因:

243586 (http://support.microsoft.com/kb/243586/) 存储过程重新编译的疑难解答

“由于某些临时表操作引起的重新编译”一节还列出了为避免一些问题(例如使用临时表导致重新编译)而需要满足的一些要求。这些限制不适用于表变量。

表变量完全独立于创建这些表变量的批,因此,当执行 CREATE 或 ALTER 语句时,不会发生“重新解析”,而在使用临时表时可能会发生“重新解析”。临时表需要此“重新解析”,以便从嵌套存储过程引用该表。表变量完全避免了此问题,因此存储过程可以使用已编译的计划,从而节省了处理存储过程的资源。

问题 3:表变量有哪些缺陷?

解答 3:与临时表相比,它存在下列缺陷:

在表变量上不能创建非聚集索引(为 PRIMARY 或 UNIQUE 约束创建的系统索引除外)。与具有非聚集索引的临时表相比,这可能会影响查询性能。
表变量不像临时表那样可以维护统计信息。在表变量上,不能通过自动创建或使用 CREATE STATISTICS 语句来创建统计信息。因此,在大表上进行复杂查询时,缺少统计信息可能会妨碍优化器确定查询的最佳计划,从而影响该查询的性能。
在初始 DECLARE 语句后不能更改表定义。
表变量不能在 INSERT EXEC 或 SELECT INTO 语句中使用。
表类型声明中的检查约束、默认值以及计算所得的列不能调用用户定义的函数。
如果表变量是在 EXEC 语句或 sp_executesql 存储过程外创建的,则不能使用 EXEC 语句或 sp_executesql 存储过程来运行引用该表变量的动态 SQL Server 查询。由于表变量只能在它们的本地作用域中引用,因此 EXEC 语句和 sp_executesql 存储过程将在表变量的作用域之外。但是,您可以在 EXEC 语句或 sp_executesql 存储过程内创建表变量并执行所有处理,因为这样表变量本地作用域将位于 EXEC 语句或 sp_executesql 存储过程中。

问题 4:与临时表或永久表相比,表变量的仅存在于内存中的结构保证了更好的性能,是否因为它们是在驻留在物理磁盘上的数据库中维护的?

解答 4:表变量不是仅存在于内存中的结构。由于表变量可能保留的数据较多,内存中容纳不下,因此它必须在磁盘上有一个位置来存储数据。与临时表类似,表变量是在 tempdb 数据库中创建的。如果有足够的内存,则表变量和临时表都在内存(数据缓存)中创建和处理。

问题 5:必须使用表变量来代替临时表吗?

解答 5:答案取决于以下三个因素:

插入到表中的行数。
从中保存查询的重新编译的次数。
查询类型及其对性能的指数和统计信息的依赖性。

在某些情况下,可将一个具有临时表的存储过程拆分为多个较小的存储过程,以便在较小的单元上进行重新编译。

通常情况下,应尽量使用表变量,除非数据量非常大并且需要重复使用表。在这种情况下,可以在临时表上创建索引以提高查询性能。但是,各种方案可能互不相同。Microsoft 建议您做一个测试,来验证表变量对于特定的查询或存储过程是否比临时表更有效。

分享到:
评论

相关推荐

    SQLServer中临时表与表变量的区别

    资源名称:SQLServer中临时表与表变量的区别内容简介: 本文档主要讲述的是SQLServer中临时表与表变量的区别;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看。资源截图: 资源太大,传百度网盘了,...

    sqlserver 循环临时表插入数据到另一张表

    sqlserver 循环临时表插入数据到另一张表 -- 声明变量 DECLARE @SupCode as varchar(100), @ProdCode as varchar(50), @PackLayer as varchar(50), @CodeStatus as varchar(50), @ProductId as varchar(50), @...

    SQLServer中临时表与表变量的区别分析

    我们在数据库中使用表的时候,经常会遇到两种使用表的方法,分别就是使用临时表及表变量。

    SQL Server 表变量和临时表的区别(详细补充篇)

    主要介绍了SQL Server 表变量和临时表的区别(详细补充篇),需要的朋友可以参考下

    sql server 临时表 查找并删除的实现代码

    考虑使用表变量而不使用临时表。当需要在临时表上显式地创建索引时,或多个存储过程或函数需要使用表值时,临时表很有用。通常,表变量提供更有效的查询处理。

    SQL Server 向临时表插入数据示例

    SQL Server 向临时表插入数据,用临时表和表变量代替游标会极大的提高性能,下面有个示例,大家可以参考下

    Microsoft SQL Server 2005技术内幕: T-SQ程序设计.pdf

    第2章 临时表和表变量  2.1 临时表  局部临时表  全局临时表  2.2 表变量  限制条件  tempdb  范围和可见性  事务上下文  统计信息  2.3 tempdb相关的注意事项  2.4 表表达式  2.5 比较临时对象  2.6 ...

    sqlserver 临时表 Vs 表变量 详细介绍

    说临时表和表变量,这是一个古老的话题,我们在网上也找到很多的资料阐述两者的特征,优点与缺点

    Microsoft SQL Server 2005 Express Edition SP3

    未及时包括在本自述文件中的任何有关 SQL Server 2005 和 SQL Server Express 的信息都将发布到 Microsoft 知识库文章 907284 中。 [顶部] 3.0 安装问题 本部分详细介绍此版本中的安装问题。 3.1 现有的 SQL ...

    SQL Server数据库技术大全 电子书

    SQL Server数据库技术大全 电子书 图书目录: 第1篇 SQL Server基础 第1章 SQL Server 2008概述/2 1.1 SQL Server 2008简介/2 1.1.1 SQL Server发展历史/2 1.1.2 SQL Server 2008的特点/4 1.2 SQL Server 2008架构...

    关于sqlserver 2005 使用临时表的问题( Invalid object name #temptb)

    最近在利用 SSRS 2005 做报表的时候,调用带有临时表的...使用一个不包含临时表的SQL语句创建报表,创建成功以后,修改数据源,替换上包含临时表的SQL命令或者存储过程,这时用SSRS 2005自带的语法检查功能对数据源语

    SQL_SERVER应用与开发范例宝典_12357672.part3

    全书分为23章,涉及到SQLServer2000、SQLServer2005、Access、Oracle10g、MySql5.0和Postgresql8.2等6种数据库语言,内容包括SQL语言基础、常规数据查询、高级数据过滤、字符串查询、日期函数、日期函数、数据排序、...

    SQL Server 2008编程入门经典(第3版)

    9.2.2 SQLServer中访问数据的方式 9.3 创建、修改和删除索引 9.3.1 CREATEINDEX语句 9.3.2 创建XML索引 9.3.3 随约束创建的隐含索引 9.3.4 在稀疏列和地理空间列上创建索引 9.4 明智地选择——在何时何地使用何种...

    (第二卷)Microsoft SQL Server 2008技术内幕:T-SQL语言基础

    亲,本人纯手工添加了书签哦!!方便阅读  《Microsoft SQL Server 2008技术内幕:T-SQL语言基础》是...10.5 临时表 10.6 动态SQL 10.7 例程 10.8 错误处理 10.9 总结 附录A SQL SERVER使用入门 索引

    SQL_SERVER应用与开发范例宝典_12357672.part2

    全书分为23章,涉及到SQLServer2000、SQLServer2005、Access、Oracle10g、MySql5.0和Postgresql8.2等6种数据库语言,内容包括SQL语言基础、常规数据查询、高级数据过滤、字符串查询、日期函数、日期函数、数据排序、...

    SQL Server2005基础教程

     11.3 临时表  11.4 聚合  11.5 GROUP BY  11.6 HAVING  11.7 独特值  11.8 函数   11.9 RAISERROR  11.10 错误处理  11.11 @@ERROR  11.12 TRY...CATCH  11.13 小结 第12章 高级T-SQL  ...

    SQLServer2000高级编程技术-已添加书签,想学存储过程、SQL编程务必要看,分析非常透彻

    10.6.4 在一个临时表中保存标识值 10.7 GUI 10.8 使用MIN或MAX函数的While循环 10.9 属性管理 10.10 小结 10.11 练习 第11章 与SQL Server环境的交互 11.1 OLE Automation对象的执行 11.1.1 sp-OACreat 11.1.2 sp-...

    SQL_SERVER应用与开发范例宝典_12357672.part1

    全书分为23章,涉及到SQLServer2000、SQLServer2005、Access、Oracle10g、MySql5.0和Postgresql8.2等6种数据库语言,内容包括SQL语言基础、常规数据查询、高级数据过滤、字符串查询、日期函数、日期函数、数据排序、...

Global site tag (gtag.js) - Google Analytics