简体   繁体   English

检查临时表中是否存在列总是在 SQL 服务器中返回 false

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

I have the following Execution statement which creates a table (using data from another procedure), inserts the values into a temporary table, adds an image column (because they cannot be included in the grouping), and then updates it based on criteria from another temporary table (the resulting table fields gets used in a SSRS report, so I need to retain the IMAGE data type):我有以下执行语句,它创建一个表(使用来自另一个过程的数据),将值插入一个临时表,添加一个图像列(因为它们不能包含在分组中),然后根据另一个标准对其进行更新临时表(生成的表字段在 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')

The problem is that regardless of whether COLUMN_A exists or not, the column for IMAGE_DATA is always NULL.问题是不管COLUMN_A是否存在,IMAGE_DATA的列总是NULL。 Is there any other way to get data into the IMAGE_DATA column?有没有其他方法可以将数据放入 IMAGE_DATA 列? Please help!请帮忙!

Note: I will not be accepting any answers that conclude that the problem is related to the content in other tables, more specifically from the WHERE clause.注意:我不会接受任何认为问题与其他表中的内容有关的答案,更具体地说,来自 WHERE 子句。 I have done multiple validations to ensure the conditions can be both true and false (matching rows, no matching rows, etc..).我已经进行了多次验证,以确保条件既可以是真也可以是假(匹配行、不匹配行等)。 So this rules out the conditional statement.所以这排除了条件语句。 Thanks.谢谢。

EDIT:编辑:

I'm still not completely sure what the exact cause of it was, but I ended up creating a global temporary table and ran two separate procedures, now it seems to be working fine.我仍然不完全确定它的确切原因是什么,但我最终创建了一个全局临时表并运行了两个单独的过程,现在它似乎工作正常。 I had to accept the answer that most closely matched my own solution.我不得不接受与我自己的解决方案最匹配的答案。 All answers and comments were very viable.所有的答案和评论都非常可行。 Thanks!谢谢!

You have several problems in your script:您的脚本中有几个问题:

  • TempDB is not the correct name of tempdb . TempDB不是tempdb的正确名称。 Your code will break on a server installed with a case sensitive collation.您的代码将在安装了区分大小写排序规则的服务器上中断。 Always use the proper case for all database names.始终对所有数据库名称使用正确的大小写。 You code is likely to break similarly on the result column names, like COLUMN_A , if run under a case sensitive deployment.如果在区分大小写的部署下运行,您的代码可能会在结果列名称(如COLUMN_A )上类似地中断。
  • The logic is incorrect under concurrency: session A will see the #temp table of session B and do incorrect actions.并发下逻辑不正确:session A 会看到 session B 的#temp 表并做错误的动作。
  • A simple test shows that the columns are visible:一个简单的测试表明这些列可见的:

. .

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')

This test shows that the column was updated, so the check for EXISTS succeeded.此测试显示列更新,因此对 EXISTS 的检查成功。 The obvious conclusion is that in your case the OBJ_ID join between #RESULTS_TABLE and #IMAGE_TABLE does not find any match, which is a problem that depends entirely on the content of your tables.显而易见的结论是,在您的情况下,#RESULTS_TABLE 和 #IMAGE_TABLE 之间的OBJ_ID连接找不到任何匹配项,这是一个完全取决于表内容的问题。

Edit编辑

You can make the COLUMN_A to be dynamic, it still works fine when tested:您可以使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;
...

You can Check if column exists in temporary table by using..您可以使用..检查临时表中是否存在列

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'

I know this is a very old thread but wanted to share my solution.我知道这是一个非常古老的线程,但想分享我的解决方案。

The problem is that TABLE_NAME returned by the INFORMATION_SCHEMA.COLUMNS view is the table name as it is stored in the tempdb.sys.objects table, which includes an indicator of session.问题是 INFORMATION_SCHEMA.COLUMNS 视图返回的 TABLE_NAME 是表名,因为它存储在 tempdb.sys.objects 表中,其中包括 session 的指示符。

You cannot use "TABLE_NAME like 'RESULTS_TABLE%'" because it is not session safe.您不能使用“TABLE_NAME like 'RESULTS_TABLE%'”,因为它不是 session 安全的。

The solution is to query the schema directly with the object id of the table instead of using the INFORMATION_SCHEMA views as follows:解决方案是直接使用表的 object id 查询架构,而不是使用 INFORMATION_SCHEMA 视图,如下所示:

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

Correct.正确的。

At the time of compilation, the column doesn't exist.在编译时,该列不存在。 That is, SQL Server looks at the whole set of commands and parses/compiles it.即 SQL 服务器查看整套命令并对其进行解析/编译。 The effects of an ALTER TABLE in the code won't be visible to later commands.代码中 ALTER TABLE 的效果对以后的命令不可见。

You have to do the ALTER TABLE separately to the UPDATE您必须对 UPDATE 单独执行 ALTER TABLE

Note: For SQL Server 2005 you'd have varbinary(max) which is far more flexible and remove some complexity注意:对于 SQL Server 2005,您将拥有更加灵活的 varbinary(max) 并消除了一些复杂性

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM