在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