58

I wrote a stored procedure to import and transform data from one database to another. Each import would take a single company ID and import all data related to this company.

To help with the transformation step I use temporary tables. As part of script review, I was told to use table variables rather than temporary tables. The reviewer claims that if we run two different imports at the same time, the temporary table would be shared and corrupt the import.


Questions:

  • Is it true that the temporary table would be shared if we run two different imports at the same time?
  • Does each call to EXEC create a new scope?

Here is a contrived example of the script.

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
4

4 回答 4

74

来自CREATE TABLE

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

和(更重要的是):

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

这恰恰反驳了谁说他们会被分享的观点。


DROP TABLE此外,在您的程序结束时不需要(再次来自同一链接):

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

于 2013-09-04T12:56:01.373 回答
50

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

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

于 2013-09-04T12:53:11.783 回答
22

一个会话看不到另一个会话的临时表。所以不同的导入不会互相影响,不管你是使用临时表还是表变量。

一个例外是全局临时表,它以##. 这些对所有连接都是可见的。

于 2013-09-04T12:52:13.250 回答
7

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

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

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

IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL
    DROP TABLE #TempTable
于 2018-05-25T07:42:27.663 回答