检查临时表中是否存在列始终在SQL Server中返回false

时间:2011-06-13 16:32:23

标签: sql sql-server tsql exec temp-tables

我有以下执行语句创建一个表(使用来自另一个过程的数据),将值插入临时表,添加一个图像列(因为它们不能包含在分组中),然后根据它更新它来自另一个临时表的条件(生成的表字段在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子句。我已经做了多次验证,以确保条件可以是真和假(匹配行,没有匹配的行等)。所以这排除了条件语句。感谢。

修改

我仍然不完全确定它的确切原因是什么,但我最终创建了一个全局临时表并运行了两个单独的程序,现在它似乎工作正常。我不得不接受最符合我自己解决方案的答案。所有答案和评论都非常可行。谢谢!

4 个答案:

答案 0 :(得分:3)

您的脚本中有几个问题:

  • TempDB不是tempdb的正确名称。您的代码将在安装了区分大小写的排序规则的服务器上中断。始终对所有数据库名称使用正确的大小写。如果在区分大小写的部署下运行,则代码可能会在结果列名称上类似地破坏,如COLUMN_A
  • 并发下逻辑错误:会话A将看到会话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;
...

答案 1 :(得分:3)

您可以使用..

检查临时表中是否存在列
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'

答案 2 :(得分:2)

正确。

在编译时,该列不存在。也就是说,SQL Server查看整组命令并解析/编译它。代码中的ALTER TABLE的效果将不会在以后的命令中显示。

您必须分别对UPDATE

执行ALTER TABLE

注意:对于SQL Server 2005,您将拥有varbinary(max),它更灵活,并且消除了一些复杂性

答案 3 :(得分:2)

我知道这是一个非常老的线程,但是想分享我的解决方案。

问题在于,由INFORMATION_SCHEMA.COLUMNS视图返回的TABLE_NAME是表名,因为它存储在tempdb.sys.objects表中,该表包含会话指示符。

您不能使用“ TABLE_NAME,如'RESULTS_TABLE%'”,因为它不是会话安全的。

解决方案是直接使用表的对象ID查询架构,而不是如下使用INFORMATION_SCHEMA视图:

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