簡體   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