CASE WHEN T-SQL中的错误结果表达式无效

时间:2018-03-15 11:53:34

标签: sql-server tsql exec case-when

我正在编写一个对表格进行疏忽的查询。问题是,基于映射文件,我想将值输入为常量或变量。

例如 - 如果在映射文件中,ExtDate是常量,例如ExtDate ='2017-12-31'我想用这个值(2017-12-31)。但是,如果ExtDate以'Var'开头,我想使用变量值 - 例如当ExtDate = VarOpenDate时,我想用列OpenDate中的值来完成列。来自MappingFile的示例行:

CREATE TABLE MappingFile (ColNum INT, Variable CHAR(50), IsUsed CHAR(50), ID CHAR(50), ExtDate CHAR(50), DataDate CHAR(50), ValueDate CHAR(50), Flag CHAR(50), Unit CHAR(50))
INSERT INTO MappingFile VALUES (1,  'ClientId', 'YES', 'VarAcctID', '2017-12-31', 'VarSigningDate', 'VarSigningDate', 'X', '')  
INSERT INTO MappingFile VALUES (2,  'ProductGroup', 'YES', 'VarAcctID', 'VarOpenDate', 'VarSigningDate', 'VarSigningDate', 'X', '')     
INSERT INTO MappingFile VALUES (3,  'ProductType', 'YES', 'VarAcctID',  'VarOpenDate', 'VarSigningDate', 'VarSigningDate', 'X', '')     

为了做到这一点,我在下面编写了一个代码(这是一个简化,因为有更多的列,整个查询在插入while循环中)。

DECLARE @I INT = 2
DECLARE @COL CHAR(50)
DECLARE @ID CHAR(50)
DECLARE @EDT CHAR(50)
DECLARE @DDT CHAR(50)
DECLARE @DTS CHAR(50) = 'dataset_name'

SET @ID  = (SELECT ID        FROM MappingFile WHERE ColNum = @I)
SET @EDT = (SELECT ExtDate   FROM MappingFile WHERE ColNum = @I)
SET @DDT = (SELECT DataDate  FROM MappingFile WHERE ColNum = @I)
SET @COL = (SELECT Variable  FROM MappingFile WHERE ColNum = @I)

EXEC('
        SELECT ''' + @DTS + ''',
                CASE WHEN SUBSTRING(''' + @ID  + ''', 1, 3) = ''Var'' THEN ' + @ID  + ' ELSE ''' + @ID  + ''' END,
                CASE WHEN SUBSTRING(''' + @EDT + ''', 1, 3) = ''Var'' THEN ' + @EDT + ' ELSE ''' + @EDT + ''' END,
                CASE WHEN SUBSTRING(''' + @DDT + ''', 1, 3) = ''Var'' THEN ' + @DDT + ' ELSE ''' + @DDT + ''' END,
                ''' + @COL + ''',
                ' + @COL + '        
FROM ' + @DTS + '
        WHERE ' + @COL + ' IS NOT NULL
        ')

不幸的是,当ExtDate是常量字符串时,查询会给我一个错误。它是由结果表达式引起的:

THEN ' + @EDT + '

返回不是列名的字符串。这给了我一个错误,尽管它不应该因为

SUBSTRING(''' + @ID  + ''', 1, 3) <> ''Var''

然后案件的结果是

' ELSE ''' + @DDT + '''

不是列名,而是常量字符串。

2 个答案:

答案 0 :(得分:0)

您已动态构建了无法解析的查询。

考虑下面的测试查询:

DECLARE @T TABLE (
    Col int
    );

INSERT INTO @T VALUES (1);

SELECT CASE 
 WHEN 1=0 THEN NoSuch ELSE 'Hi' END
 FROM @T;

运行此命令,结果为

  

消息207,级别16,状态1,行8无效的列名称&#39; NoSuch&#39;。

因为即使CASE没有执行THEN并跳到ELSE,解析器也不会事先知道并检查以确保NoSuch是一列。如果不是,它会在尝试运行之前拒绝查询。

一种解决方案是检查动态字符串的变量OUTSIDE。

答案 1 :(得分:0)

感谢@Tab Alleman,我设法找到了解决方案。关于解析器的现象是完全正确的,因此我必须检查EXEC命令之外的变量。

下面找到有效的代码:

/*Redirect your log file*/
proc printto log='../Processlog/processlog.txt';
   run;
/* Your Code Here */
/* Reset log path to default */
proc printto;
run;