SQL Server 2012 在sp_executesql 中生成的臨時表的可見性

在sql存儲過程中,經常使用到動態sql語句,寫法類似於這樣

Set @strParameter=N'@StartTime datetime,@EndTime datetime'
Exec sp_executesql @strSql,@strParameter,@StartTime,@EndTime    

爲了滿足業務需求,我們經常會在存儲過程中使用到臨時表。根據作用域的不同,分爲全局臨時表和用戶臨時表。

如果在動態sql語句中構造了用戶臨時表,代碼如下:

exec SP_EXECUTESQL N'SELECT * INTO #temp FROM TestTable' 
SELECT * FROM #temp

執行後會報如下錯誤

消息 208,級別 16,狀態 0,第 37 行
對象名 '#temp' 無效。

在ssms中調試,執行到該動態SQL語句時
會出現異常“未將對象設置引用到對象實例”
這是由於臨時表只存在於動態sql這個作用域內,也就是隻在動態SQL可見,在當前存儲過程中是不可見的,所以會出現找不到該臨時表的錯誤。

首先創建測試表

IF object_id('TestTable') IS NOT NULL
    DROP TABLE TestTable
GO

CREATE TABLE TestTable(id INT IDENTITY(1,1),Info VARCHAR(10))
GO
INSERT TestTable SELECT 'a'
UNION ALL SELECT 'b'
GO

然後依次執行以下三個腳本

腳本一:

EXEC('SELECT * INTO #temp FROM TestTable')
SELECT * FROM #temp

腳本二:

exec SP_EXECUTESQL N'SELECT * INTO #temp FROM TestTable' 
SELECT * FROM #temp

腳本三:

SELECT * INTO #temp FROM TestTable
EXEC('SELECT * FROM #temp')

–DROP TABLE #temp

執行後發現只有腳本三是成功的,其他連個腳本執行後都會提示:

Msg 208, Level 16, State 0, Line 2
Invalid object name '#temp'.

知道了問題出現的原因,解決方案很簡單,將用戶臨時表替換爲全局臨時表就ok了,也就是在#temp前再加個‘#’,即 ##Temp

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章