2012-07-16 145 views
0

我在兩個單獨的存儲過程中使用#temp表。在一種情況下,它工作正常,而在其他情況下,它會給出錯誤「無效的對象名稱#temp」。動態SQL和字段名稱數組中的對象名稱#temp無效

第一種情況:

SELECT SubsID, 
       SubsName, 
       AbbrName 
INTO   #TEMP 
FROM   SubsList 
WHERE  CAST (SubsID AS VARCHAR(10)) LIKE '%' + @intRight + '%' 
        OR SubsName LIKE '%' + @intRight + '%' 

它好的工作。

爲了使這個SQL更具動態性,我使用QUOTENAME並做了以下更改: 1.我將@ColName,@sourceName,@intField和@txtField的數據類型設爲sysname。 2.事實上,我刪除了param @tableName作爲sysname(值:#temp被傳遞給它),因爲它在Select和Drop SQL中給出了錯誤。 3.我在@ColName中傳遞一個字段名稱。當我通過所有三個字段名稱時,它給了錯誤。 4.我聲明@cmd nvarchar(max)併爲其分配SQL以供執行。

SET @cmd = N'Select ' + QUOTENAME(@ColName) + 
      N' INTO #temp from ' + QUOTENAME(@sourceName) + 
      N' where CAST(' + QUOTENAME(@intField) + N' AS VARCHAR(10)) like ''%' + @strVal + 
      N'%'' or ' + QUOTENAME(@txtField) + ' like ''%' + @strVal + N'%''' --working 
EXEC sp_executesql @cmd; 

SELECT * 
FROM #temp; 

DROP TABLE #temp; 

我將EXEC sp_executesql @cmd更改爲EXEC(@cmd),但仍然存在錯誤。

我得到無效對象名稱的錯誤,但是如果我將#temp更改爲## temp,則此錯誤不存在。

我的第一個問題:在使用#temp的情況下,這個錯誤有什麼原因? 第二個問題:我如何製作字段名稱數組並將其傳遞給存儲過程?

+0

您應該將'@ strVal'作爲參數傳遞給'sp_executesql',而不是將其簡單地連接到爲避免SQL注入而執行的字符串中。 – 2012-07-16 14:29:19

回答

2

exec完成後,temp表超出了範圍。'exec'或'sp_executesql'在他們自己的範圍內運行。因此,像臨時表和變量一樣創建的任何東西都會在執行結束後被銷燬或超出範圍。認爲這些存儲過程像存儲過程一樣。

修復此問題。在主代碼中創建臨時表..然後使用dynmic sql插入它,然後在主代碼中讀取它。

+0

請訪問以下鏈接,其中EXEC和sp_executesql以非常好的方式進行了解釋。即使例子也很好理解: http://www.sommarskog.se/dynamic_sql.html#sp_executesqlong – 2012-07-19 02:59:18