开发者

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

I have the f开发者_如何学编程ollowing 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):

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. Is there any other way to get data into the IMAGE_DATA column? 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. 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. 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.
  • The logic is incorrect under concurrency: session A will see the #temp table of session B and do incorrect actions.
  • 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. 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.

Edit

You can make the COLUMN_Ato be dynamic, it still works fine when tested:

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;
...


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.

You cannot use "TABLE_NAME like 'RESULTS_TABLE%'" because it is not session safe.

The solution is to query the schema directly with the object id of the table instead of using the INFORMATION_SCHEMA views as follows:

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. The effects of an ALTER TABLE in the code won't be visible to later commands.

You have to do the ALTER TABLE separately to the UPDATE

Note: For SQL Server 2005 you'd have varbinary(max) which is far more flexible and remove some complexity


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜