繁体   English   中英

SQL Server中临时表的范围

[英]Scope of temporary tables in SQL Server

我编写了一个存储过程,以将数据从一个数据库导入并转换到另一个数据库。 每次导入都将使用一个公司ID,并导入与此公司相关的所有数据。

为了帮助进行转换,我使用了临时表。 在脚本审查中,有人告诉我使用表变量而不是临时表。 审阅者声称,如果我们同时运行两个不同的导入,则临时表将被共享并破坏导入。


问题:

  • 如果我们同时运行两个不同的导入,是否可以共享临时表?
  • 是否每个对EXEC调用都会创建一个新的作用域?

这是该脚本的虚构示例。

CREATE PROC [dbo].[ImportCompany]
(
    @CompanyId AS INTEGER
)
AS
EXEC [dbo].[ImportAddress] @CompanyId = @CompanyId 
--Import other data

CREATE PROC [dbo].[ImportAddress]
(
    @CompanyId AS INTEGER
)
AS
    CREATE TABLE #Companies (OldAddress NVARCHAR(128), NewAddress NVARCHAR(128))
    INSERT INTO #Companies(OldAddress, NewAddress)
    SELECT
        Address as OldAddress,
        'Transformed ' + Address as NewAddress
    FROM
        [OldDb].[dbo].[Addresses]
    WHERE
        CompanyId = @CompanyId

    --Do stuff with the transformed data

    DROP TABLE #Companies

EXEC [dbo].[ImportCompany] @CompanyId = 12345

CREATE TABLE

本地临时表仅在当前会话中可见

和(更重要的是):

如果在可以由多个用户同时执行的存储过程或应用程序中创建了本地临时表,则数据库引擎必须能够区分由不同用户创建的表[原文-几乎可以肯定的是,会话不是用户] 数据库引擎通过在内部将数字后缀附加到每个本地临时表名称来实现此目的。

无论谁说他们将被分享,这都恰恰反驳了这一点。


另外,在过程结束时也无需DROP TABLE (再次从同一链接):

存储过程完成后,将自动删除在存储过程中创建的本地临时表

##用于全局临时表-将可用于不同的导入。

#用于本地临时表,仅在当前/内部范围内可用。

一个会话无法看到另一会话的临时表。 因此,无论您使用临时表还是表变量,不同的导入都不会互相影响。

全局临时表例外,该临时表以##开头。 这些对所有连接都是可见的。

我只花了几个小时苦苦挣扎,以找出触发器中使用的临时表为何表现异常。 然后我意识到临时表与存储过程中的临时表同名,该存储过程用于插入触发触发器的数据。 我现在知道这对我本来应该是显而易见的,但是这是一个典型的案例,当试图找出为什么没有意义的时候却忽略了最明显的原因。

因此,重要的是要记住,当一个存储的proc调用另一个存储的proc或触发一个触发器时,临时表名称必须在所有这些表中都是唯一的,以防止出现不良的副作用。

此外-即使在内部存储的proc中执行以下代码,它也不会按预期运行。 由于外部存储的proc似乎锁定了临时表的名称。

IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL
    DROP TABLE #TempTable

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM