簡體   English   中英

檢查臨時表中是否存在列總是在 SQL 服務器中返回 false

[英]Checking if column exists in temporary table always returns false in SQL Server

我有以下執行語句,它創建一個表(使用來自另一個過程的數據),將值插入一個臨時表,添加一個圖像列(因為它們不能包含在分組中),然后根據另一個標准對其進行更新臨時表(生成的表字段在 SSRS 報告中使用,因此我需要保留 IMAGE 數據類型):

EXEC ('SELECT ' + @COL_TO_GROUP_BY + @COL_ADDITONAL + @sColVals + ' INTO
#RESULTS_TABLE from (' + @SQL_STATEMENT + ') A ' + @WHERE_CLAUSE + ' GROUP BY ' +
@COL_TO_GROUP_BY +

' ALTER TABLE #RESULTS_TABLE
ADD IMAGE_DATA IMAGE

IF EXISTS(SELECT * FROM tempdb.INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = 
''COLUMN_A'' and TABLE_NAME LIKE ''#RESULTS_TABLE%'')
BEGIN
    UPDATE #RESULTS_TABLE
    SET IMAGE_DATA = FILE_DATA
    FROM #RESULTS_TABLE A, #IMAGE_TABLE B 
    WHERE A.COLUMN_A = B.COLUMN_A
END

SELECT * FROM #RESULTS_TABLE')

問題是不管COLUMN_A是否存在,IMAGE_DATA的列總是NULL。 有沒有其他方法可以將數據放入 IMAGE_DATA 列? 請幫忙!

注意:我不會接受任何認為問題與其他表中的內容有關的答案,更具體地說,來自 WHERE 子句。 我已經進行了多次驗證,以確保條件既可以是真也可以是假(匹配行、不匹配行等)。 所以這排除了條件語句。 謝謝。

編輯:

我仍然不完全確定它的確切原因是什么,但我最終創建了一個全局臨時表並運行了兩個單獨的過程,現在它似乎工作正常。 我不得不接受與我自己的解決方案最匹配的答案。 所有的答案和評論都非常可行。 謝謝!

您的腳本中有幾個問題:

  • TempDB不是tempdb的正確名稱。 您的代碼將在安裝了區分大小寫排序規則的服務器上中斷。 始終對所有數據庫名稱使用正確的大小寫。 如果在區分大小寫的部署下運行,您的代碼可能會在結果列名稱(如COLUMN_A )上類似地中斷。
  • 並發下邏輯不正確:session A 會看到 session B 的#temp 表並做錯誤的動作。
  • 一個簡單的測試表明這些列可見的:

.

EXEC ('SELECT * INTO #RESULTS_TABLE from 
     (select *, newid() as COLUMN_A from master..spt_values) A;
ALTER TABLE #RESULTS_TABLE
ADD IMAGE_DATA varbinary(max);
IF EXISTS(SELECT * FROM TempDB.INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = 
''COLUMN_A'' and TABLE_NAME LIKE ''#RESULTS_TABLE%'')
BEGIN
    update #RESULTS_TABLE 
       set IMAGE_DATA = 0xBAADF00D;
END
SELECT * FROM #RESULTS_TABLE')

此測試顯示列更新,因此對 EXISTS 的檢查成功。 顯而易見的結論是,在您的情況下,#RESULTS_TABLE 和 #IMAGE_TABLE 之間的OBJ_ID連接找不到任何匹配項,這是一個完全取決於表內容的問題。

編輯

您可以使COLUMN_A成為動態的,它在測試時仍然可以正常工作:

declare @cn sysname = case 
      when RAND() * 100 >= 50 then 'COLUMN_A' 
      else 'COLUMN_B' end;

EXEC (N'SELECT * INTO #RESULTS_TABLE from (
     select *, newid() as ' + @cn + N'  from master..spt_values) A;
...

您可以使用..檢查臨時表中是否存在列

IF EXISTS (SELECT * FROM TempDB.INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = 'Column' AND TABLE_NAME LIKE '#TempTable%')
    PRINT 'Column exists'
ELSE
    PRINT 'Column doesn''t exists'

我知道這是一個非常古老的線程,但想分享我的解決方案。

問題是 INFORMATION_SCHEMA.COLUMNS 視圖返回的 TABLE_NAME 是表名,因為它存儲在 tempdb.sys.objects 表中,其中包括 session 的指示符。

您不能使用“TABLE_NAME like 'RESULTS_TABLE%'”,因為它不是 session 安全的。

解決方案是直接使用表的 object id 查詢架構,而不是使用 INFORMATION_SCHEMA 視圖,如下所示:

if exists (Select 1 
           from tempdb.sys.columns 
           where [object_id] = object_id('tempdb..#RESULTS_TABLE') 
             and name ='COLUMN_A')

正確的。

在編譯時,該列不存在。 即 SQL 服務器查看整套命令並對其進行解析/編譯。 代碼中 ALTER TABLE 的效果對以后的命令不可見。

您必須對 UPDATE 單獨執行 ALTER TABLE

注意:對於 SQL Server 2005,您將擁有更加靈活的 varbinary(max) 並消除了一些復雜性

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM