SQL Server中临时表的范围

Cog*_*ave 44 sql t-sql sql-server sql-server-2012

我编写了一个存储过程来将数据从一个数据库导入和转换到另一个数据库 每次导入都会获取一个公司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
Run Code Online (Sandbox Code Playgroud)

Dam*_*ver 55

来自CREATE TABLE:

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

(更重要的是):

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

这恰恰反驳了谁说他们将被分享的观点.


此外,DROP TABLE您无需在程序结束时(再次从同一链接):

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

  • 语句_可以由多个用户同时执行,数据库引擎必须能够区分由不同用户创建的表_令人困惑!似乎不同会话中的“相同用户”共享临时表。而且不是那样。 (2认同)

Dar*_*ren 34

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

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

  • 内部作用域中也可以看到本地临时表,例如:http://sqlfiddle.com/#!6/d41d8/6725/1 (3认同)

And*_*mar 19

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

例外的是全局临时表,它以##.所有连接都可以看到这些.


Nel*_*loo 7

我只是花了几个小时努力找出为什么触发器中使用的临时表表现得很奇怪。然后我意识到临时表与用于插入触发触发器的数据的存储过程中的临时表具有相同的名称。我现在意识到这对我来说应该是显而易见的,但这是一个典型的案例,在试图找出为什么某些事情没有意义时忽略了最明显的原因。

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

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

IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL
    DROP TABLE #TempTable
Run Code Online (Sandbox Code Playgroud)

  • 我觉得这个答案可能有帮助并且与问题相关,但是如果您可以更改措辞以使其更清楚它如何直接影响 OP 所询问的情况,那么它可能会更好地接受。 (2认同)