SQL Server 临时表和连接池

35

我有一个针对SQL Server运行的多用户ASP.NET应用程序,希望StoredProcA创建#temptable临时表(不是表变量)来插入一些数据,然后分别调用StoredProcB、StoredProcC和StoredProcD,根据业务规则操作#temptable中的数据。

当与SQL通信时,Web应用程序使用连接池。每次调用StoredProcA都会得到一个新的#temptable临时区域吗?还是连接池会在用户之间共享#temptable?

6个回答

54

1
好的,现在这个语句对我来说有意义了:“当表格前面有单个‘#’符号时,它被定义为本地临时表,其范围仅限于创建它的会话。”“会话”这个词让我感到困惑! - marc
全局可见的临时表(##tableName)怎么样? - Andrei Rînea
全局临时表不受连接范围限制,因此它们不会被删除。 - Mark Brackett

7

所有用户都将共享一张##表格。我认为这不是你的意图。

一个单独的#临时表格对于调用堆栈中的所有存储过程可见,但在该范围之外不可见。如果您可以让Proc A调用B、C和D,那么应该没问题。

编辑:我现在应该在处理类似于此的报告程序。 :)我在由应用程序调用的根过程中创建了一个临时表格(#results),然后在一系列子过程中进行了一些复杂的数据操作,以1)抽象重复代码,2)避免根过程运行到500多行。


顺便说一下,这是一个非常好的 S.O. 问题;每个人在某个时候都会问到的问题。我敢打赌,这将成为那些驱动 Google 流量并且总有一天至少会获得银徽章的问题之一。 - Kevin

3

#temptable声明的存储过程结束后就不再存在,因此其他用户将永远无法看到它。

编辑:嘿,事实证明,自SQL Server 7.0以来,临时表的“嵌套可见性”就已经可以使用了,但我从未更新过任何代码来利用这一点。我想我正在让自己过时了——很多人可能无法想象曾经是在SQL Server 6.0和6.5中翻遍天地的苦难日子...


1
#temptable的作用域是连接的范围,而不是过程的范围。 - Amy B
这是一个引用链接:http://decipherinfosys.wordpress.com/2007/05/04/temporary-tables-ms-sql-server/ - Curt Hagenlocher
1
我明白了,脚本级别创建的#temp表和存储过程内创建的#temp表是不同的。谢谢。 - Amy B
但是它仍然会在被调用的过程中可见! :) - Amy B
这会在.NET中的SqlCommand中造成一个巨大的问题。根据SqlCommand的构造方式,它可能会或可能不会将自己包装在存储过程中,因此在SqlCommand中创建的临时表可能会或可能不会对在同一连接上运行的后续SqlCommand可见。 - Triynko
显示剩余2条评论

2

根据MS文档:

http://msdn.microsoft.com/en-us/library/ms177399(SQL.90).aspx

临时表

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

有两种类型的临时表:本地和全局。它们在名称、可见性和可用性方面有所不同。 本地临时表以单个数字符号(#)作为其名称的第一个字符;它们仅对用户的当前连接可见,并且在用户从SQL Server实例断开连接时被删除。

全局临时表以两个数字符号(##)作为其名称的前两个字符;它们在创建后对任何用户可见,并且在所有引用该表的用户从SQL Server实例断开连接时被删除。

例如,如果您创建了表employees,那么只要有权限的人可以使用该表,直到该表被删除。如果数据库会话创建本地临时表#employees,则只有该会话可以使用该表,并且在会话断开时删除。如果您创建全局临时表##employees,则数据库中的任何用户都可以使用此表。如果在您创建该表后没有其他用户使用该表,则在断开连接时删除该表。如果另一个用户在您创建它后使用该表,则SQL Server在您断开连接并且所有其他会话不再积极使用它之后将其删除。

此外,根据Curt的补充(如果您错过了评论中的引用):

http://msdn.microsoft.com/en-us/library/ms191132.aspx

  • 如果在存储过程内部创建本地临时表,则该临时表仅存在于存储过程的目的中;当您退出存储过程时,它会消失。

  • 如果执行调用另一个存储过程的存储过程,则被调用的存储过程可以访问由第一个存储过程创建的所有对象,包括临时表。


1
他明确表示他正在使用存储过程。如果临时表位于连接的“顶层”,你所说的是正确的,但当它在存储过程内部使用时,它会在结束时自动删除。我会在官方文档中寻找引用。 - Curt Hagenlocher
2
如果您在存储过程中创建一个本地临时表,那么该临时表仅存在于存储过程的范围内;当您退出存储过程时,它将消失。 - Curt Hagenlocher

1

要在用户之间共享临时表,请在名称前使用两个井号##like_this。

在这种情况下,确保采取措施避免程序的多个实例之间发生冲突。


0

临时表在幕后使用名称混淆创建,因此不应该存在不同存储过程调用之间的冲突。

如果您需要在后续存储过程调用中操作相同的临时数据,则最好使用真实表并使用某种唯一标识符来确保您只处理相关数据。如果数据仅有临时价值,请在完成后手动删除它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接