我正在编写一个对表格进行疏忽的查询。问题是,基于映射文件,我想将值输入为常量或变量。
例如 - 如果在映射文件中,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 + '''
不是列名,而是常量字符串。
答案 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;