2011-06-13 104 views
4

我有以下执行语句,它创建一个表(使用另一个过程中的数据),将这些值插入临时表,添加图像列(因为它们不能被包括在该分组中),然后更新它基于从另一个临时表的标准(所得到的表中的字段被在SSRS报告中使用,所以需要保留所述图像数据类型):检查临时表中是否存在列总是在SQL Server中返回false

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子句。我已经完成了多个验证,以确保条件可以是true和false(匹配行,不匹配行等)。所以这就排除了条件陈述。谢谢。

编辑:

我还没有完全知道是什么它的确切原因是,但我结束了创建一个全局临时表,跑两个不同的过程,现在看来是工作的罚款。我不得不接受与我自己的解决方案最匹配的答案。所有的答案和评论都非常可行。谢谢!

+0

首先,我会试着省略'WHERE A.COLUMN_A = B.IMAGE_VALUE'这对我来说这足以通过'OBJ_ID'找到正确的行。 – 2011-06-13 16:38:46

+0

谢谢你指出。在我的情况下,我需要有两个条件,因为有一些重复的OBJ_ID行。我简化了我的原始代码,应该把它看成是误导性的。我将编辑该问题。 – 2011-06-13 16:55:33

+0

不知道这是否有帮助,但我认为你可以在你的SELECT语句中像这样将'image(null作为图像)添加为IMAGE_DATA',而不必将它添加到group by子句中,因为它是一个常量。顺便说一句,为什么你需要测试列是否存在? – 2011-06-13 17:53:08

回答

2

正确。

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

你有

注分别做ALTER TABLE到UPDATE:对于SQL Server 2005,你就必须VARBINARY(最大),这是更为灵活,并删除了一些复杂

+0

感谢您的回复。我正在使用SQL Server 2008.我尝试将图像列转换为varbinary(max),甚至是从二进制文件(根据其他建议)将varbinary转换为varbinary,但它给了我乱码,所以这不是一个选项。你能否请澄清我应该怎样做ALTER TABLE与UPDATE分开?执行两个EXEC语句超出临时表的作用域。谢谢。 – 2011-06-13 17:04:52

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

感谢您的回答。请参阅对问题的编辑。袒护我,因为这是我使用这个论坛的第一个问题,所以我应该首次提出这个问题。我会尝试使用您用于测试的过程。 – 2011-06-13 19:21:17

+0

没有违法,但每当我面对'你的话与测试行为'我选择'测试行为'。球在你的球场上,你需要证明IF分支没有被采取。 – 2011-06-13 19:29:25

+0

我看着你的脚本,意识到你的执行方式与我的方式有所不同。我的脚本没有明确创建COLUMN_A。 COLUMN_A根据从另一个过程(另一个表)提取的内容显示,因此是动态的。你是对的,如果我这样做,它会正常工作(在这种情况下,我可能根本不需要进行检查)。我认为问题在于动态创建的列。 – 2011-06-13 19:52:42

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'