Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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!

like image 969
Carmen W Avatar asked Jan 20 '23 12:01

Carmen W


2 Answers

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;
...
like image 177
Remus Rusanu Avatar answered Jan 30 '23 22:01

Remus Rusanu


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')
like image 45
basage24 Avatar answered Jan 30 '23 21:01

basage24