`
feiliboos
  • 浏览: 664471 次
文章分类
社区版块
存档分类
最新评论

sql server 表变量和临时表

 
阅读更多

临时表与永久表相似,但临时表存储在 tempdb 中,当不再使用时会自动删除。

临时表有两种类型:本地和全局。它们在名称、可见性以及可用性上有区别。本地临时表的名称以单个数字符号 (#) 打头;它们仅对当前的用户连接是可见的;当用户从 SQL Server 实例断开连接时被删除。全局临时表的名称以两个数字符号 (##) 打头,创建后对任何用户都是可见的,当所有引用该表的用户从 SQL Server 断开连接时被删除。

例如,如果创建了 employees 表,则任何在数据库中有使用该表的安全权限的用户都可以使用该表,除非已将其删除。如果数据库会话创建了本地临时表 #employees,则仅会话可以使用该表,会话断开连接后就将该表删除。如果创建了 ##employees 全局临时表,则数据库中的任何用户均可使用该表。如果该表在您创建后没有其他用户使用,则当您断开连接时该表删除。如果您创建该表后另一个用户在使用该 表,则 SQL Server 将在您断开连接并且所有其他会话不再使用该表时将其删除。

临时表

临时表存储在TempDB数据库中,所有的使用此SQL Server 实例的用户都共享这个TempDB,因为我们应该确保用来存储TempDB数据库的硬盘有足够的空间,以使之能够自己的增长.最好能够存储在一个拥有独立 硬盘控制器上.因为这样不存在和其它的硬盘I/O进行争用.

我们很多程序员认为临时表非常危险,因为临时表有可能被多个连接所共享.其实在SQL Server中存在两种临时表:局部临时表和全局临时表,局部临时表(Local temp table)以#前缀来标识,并且只能被创建它的连接所使用.全局临时表(Global temp table)以##前缀来进行标识,并且可以和其它连接所共享.

局部临时表

局部临时表不能够被其它连接所共享的原因其实是在SQL Server 2000中自动为局部临时表的表名后面加上了一个唯一字符来标识.如:

CREATE TABLE [#DimCustomer_test]

(

[CustomerKey] [int]

, [FirstName] [nvarchar](50)

,[MiddleName] [nvarchar](50)

,[LastName] [nvarchar](50)

)

现在我们来查看一下TempDB中 sysobjects表,我们会发现我们新创建的临时表#DimCustomer_test已经被加上了后缀:

USE TempDB

GO

SELECT name FROM sysobjects WHERE name LIKE ’%DimCustomer%’

the Result is:

name

#DimCustomer_test___________________________________________________________________________________________________000000000005

全局临时表

下面我们来看一下全局临时表:

CREATE TABLE [##DimCustomer_test]

(

[CustomerKey] [int]

, [FirstName] [nvarchar](50)

,[MiddleName] [nvarchar](50)

,[LastName] [nvarchar](50)

)

现在我们来查看一下TempDB中 sysobjects表,我们会发现我们新创建的临时表##DimCustomer_test没有被加上了后缀:

USE TempDB

GO

SELECT name FROM sysobjects WHERE name LIKE ’%DimCustomer%’

The Result are:

#DimCustomer_test___________________________________________________________________________________________________000000000005

##DimCustomer_test

--Drop test temp tables

DROP TABLE [##DimCustomer_test]

DROP TABLE [#DimCustomer_test]

可以看到我们刚才创建的全局临时表名字并没有被加上标识.

表变量

表变量和临时表针对我们使用人员来说并没有什么不同,但是在存储方面来说,他们是不同的,表变量存储在内存中.所以在性能上和临时表相比会更好些!

另一个不同的地方是在表连接中使用表变量时,要为此表变量指定别名.如:

USE AdventureWorksDW

GO

DECLARE @DimCustomer_test TABLE

(

[CustomerKey] [int]

, [FirstName] [nvarchar](50)

,[MiddleName] [nvarchar](50)

,[LastName] [nvarchar](50)

)

---insert data to @DimCustomer_test

INSERT @DimCustomer_test

(

[CustomerKey]

, [FirstName]

,[MiddleName]

,[LastName]

)

SELECT

[CustomerKey]

, [FirstName]

,[MiddleName]

,[LastName]

FROM DimCustomer

SELECT [@DimCustomer_test].CustomerKey,SUM(FactInternetSales.OrderQuantity)

FROM @DimCustomer_test INNER JOIN FactInternetSales ON

@DimCustomer_test.CustomerKey = FactInternetSales.CustomerKey

Group BY CustomerKey

Result:

Server: Msg 137, Level 15, State 2, Line 32

Must declare the variable ’@DimCustomer_test’.

如果我们对上面的查询进行更改,对查询使用别名(并且找开IO):

-----in the follow script,we used the table alias.

DECLARE @DimCustomer_test TABLE

(

[CustomerKey] [int]

, [FirstName] [nvarchar](50)

,[MiddleName] [nvarchar](50)

,[LastName] [nvarchar](50)

)

INSERT @DimCustomer_test

(

[CustomerKey]

, [FirstName]

,[MiddleName]

,[LastName]

)

SELECT

[CustomerKey]

, [FirstName]

,[MiddleName]

,[LastName]

FROM DimCustomer

SELECT t.CustomerKey,f.OrderQuantity

FROM @DimCustomer_test t INNER JOIN FactInternetSales f ON

t.CustomerKey = f.CustomerKey

where t.CustomerKey=13513

表变量在批处理结束时自动被系统删除,所以你不必要像使用临时表表一样显示的对它进行删除.
表变量主要开销系统的内存,而临时表则使用tempdb。对于小数据量的中间数据存储,可以使用表变量,而当需要临时保存的数据量很庞大时,建议使用临时表。具体使用表变量还是临时表,可以根据系统的运行状况来调整。

====================================================

例如,如果创建名为 employees 的表,则任何人只要在数据库中有使用该表的安全权限就可以使用该表,除非它已删除。如果创建名为 #employees 的本地临时表,只有您能对该表执行操作且在断开连接时该表删除。如果创建名为 ##employees 的全局临时表,数据表中的任何用户均可对该表执行操作。如果该表在您创建后没有其他用户使用,则当您断开连接时该表删除。如果该表在您创建后有其他用户使 用,则 SQL Server在所有用户断开连接后删除该表。

=====================================================

非索引视图只是一个定义, 不存储数据, 查询的时候才从基础表拿数据

索引视图会存储数据

索引视图和临时表的数据都存储在硬盘

其中索引视图的数据存储在视图所在的数据库文件中

临时表的数据存储在tempdb这个数据库文件中

问题 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 建议您做一个测试,来验证表变量对于特定的查询或存储过程是否比临时表更有效。

分享到:
评论

相关推荐

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

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

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

    资源名称: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), @...

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

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

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

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

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

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

    Microsoft SQL Server 2005 Express Edition SP3

    如果您的计算机已安装 SQL Server 2000 管理工具和 SQL Server Express 的默认实例,则可以使用 SQL Server 安装程序安装 SQL Server 2000 的默认实例。但是,这样做会禁用已安装的 SQL Server Express 实例。因此,...

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

    1.6.3 系统数据库msdb——为SQL Server提供队列和可靠消息传递/26 1.6.4 系统数据库tempdb——临时工作区/26 1.7 示例数据库/27 1.7.1 安装示例数据库/27 1.7.2 示例数据库AdventureWorks/29 1.7.3 示例数据库...

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

    6.7.3 确定哪个表和数据类型使用给定的规则或默认值 6.8 用于实现数据完整性的触发器 6.9 如何选择 6.1 0本章小结 第7章 更复杂的查询 7.1 子查询的概念 7.2 关联子查询 7.2.1 关联子查询的工作原理 7.2.2 在WHERE...

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

    1.3 创建表和定义数据完整性 1.4 总结 第2章 单表查询 2.1 SELECT语句的元素 2.2 谓词和运算符 2.3 CASE表达式 2.4 NULL值 2.5 同时操作(ALL-AT-ONCE OPERATION) 2.6 处理字符数据 2.7 处理...

    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  ...

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

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

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

    第2章 关系数据库概念和SQL Server环境 2.1 数据库 2.1.1 关系数据库 2.1.2 数据库对象 2.1.3 什么是存储过程 2.2 SQL Server 2000的工具 2.2.1 Service Manage 2.2.2 Query Analyze 2.2.3 Enterprise Manage 2.2.4 ...

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

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

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

    6.7.3 确定哪个表和数据类型使用给定的规则或默认值 6.8 用于实现数据完整性的触发器 6.9 如何选择 6.1 0本章小结 第7章 更复杂的查询 7.1 子查询的概念 7.2 关联子查询 7.2.1 关联子查询的工作原理 7.2.2 在WHERE...

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

    1.3 创建表和定义数据完整性 1.4 总结 第2章 单表查询 2.1 SELECT语句的元素 2.2 谓词和运算符 2.3 CASE表达式 2.4 NULL值 2.5 同时操作(ALL-AT-ONCE OPERATION) 2.6 处理字符数据 2.7 处理日期和时间...

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

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

Global site tag (gtag.js) - Google Analytics