繁体   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