我需要能够在Aginity Workbench和SAS之间复制粘贴一个包含变量的长SQL脚本。为了简化这一点,我将SQL查询存储在一个宏变量中,如下所示: (注意Netezza样式变量)
%let myQuery = %str(
DROP TABLE this;
SELECT *
INTO SomeTable
FROM OtherTable
WHERE field = ${myVariable};
UPDATE TABLE foo
SET x = 1
WHERE
field = ${anotherVariable};
);
当我的SAS程序运行时,我需要它将 $ {netezzaVariables} 替换为前面在流程流中确定的其他宏变量中的文本。到目前为止,我还没能成功替换此宏变量中的文本,我怀疑分号是否会导致问题。
这是我在下面尝试做的事情:
%let formattedText = %sysfunc(tranwrd(&myQuery,'${myVariable}','replacementText'));
该日志显示:
NOTE: Line generated by the macro function "SYSFUNC".
DROP TABLE this;
! SELECT <the rest of the query is printed to console here>
我没有继续编写上面的其余日志,因为错误出现在单词SELECT上,下面有一条红线。在这条红线下方是文字:
ERROR 180-322:声明无效或使用不正确。
事实上,如果我继续滚动日志,查询中分号后面的每个第一组字符都会用相同的错误代码加下划线。 这让我相信SAS在SELECT之前拿了分号,用它来终止我正在做的事情,现在认为这个分号后面的文字在开放代码中出来了。
总之,我需要知道如何在宏变量中替换子字符串,该变量的值是包含分号的大字符串。
提前致谢!
答案 0 :(得分:0)
在使用%sysfunc()
字符串函数时,您不需要使用引号。在这种情况下,我认为%qsysfunc
是您正在寻找的:
%let myQuery = %str(
DROP TABLE this;
SELECT *
INTO SomeTable
FROM OtherTable
WHERE field = ${myVariable};
UPDATE TABLE foo
SET x = 1
WHERE
field = ${anotherVariable};
);
%put &myQuery;
%let formattedText = %qsysfunc(tranwrd(&myQuery,${myVariable},replacementText));
%put &formattedText;
答案 1 :(得分:0)
不是最优雅的解决方案,但它可以完成任务:
%let myQuery = %str(
DROP TABLE this;
SELECT *
INTO SomeTable
FROM OtherTable
WHERE field = ${myVariable};
UPDATE TABLE foo
SET x = 1
WHERE
field = ${anotherVariable};
);
data _null_;
call symput('formattedtext',tranwrd("%quote(%superq(myquery))","${myVariable}","replacementText"));
run;
%put %superq(formattedText);
可能有一种方法只使用宏功能,但我无法使用它。
对于您的特定示例,call symput
可能已简化为
call symput('formattedtext',tranwrd("&myquery","${myVariable}","replacementText"));
但如果您的查询包含双引号,则会失败,而我上面写的方式则支持。
答案 2 :(得分:0)
约书亚:
如果你的模板&#39;是通用解析器很有用。表达式有很多参数。注意:模板与参数化查询不同,可能更危险。
如果没有解析器,您需要为每个参数编写TRANWRD。
考虑这个宏,假设模板包含由$ { macro-var }指定的参数,并且参数被宏变量值替换。还假设没有以下划线(_)开头的参数可能会与宏内部变量发生冲突。
%macro resolver(_template);
%local _result;
%local _tokenRx;
%local _start _stop _position _length _token _macrovar _guard;
%let _tokenRx = %sysfunc(prxparse(m/\${([^}]+)}/));
/*%put &=_tokenRx;*/
%let _guard = 0;
%let _start = 1;
%let _stop = %length(&_template);
%let _position = 0;
%let _length = 0;
%let _result = &_template;
%syscall prxnext(_tokenRx, _start, _stop, _template, _position, _length);
%do %while (&_position > 0);
/* %put &=_start &=_stop &=_position &=_length; */
%let _token = %qsubstr(&_template,&_position,&_length);
%let _macrovar = %substr(&_token,3,%eval(%length(&_token)-3));
/*
%put &=_token;
%put &=_macrovar;
*/
%if %symexist(&_macrovar) %then %do;
%let _result = %qsysfunc(tranwrd(&_result,&_token,&&&_macrovar));
%end;
%syscall prxnext(_tokenRx, _start, _stop, _template, _position, _length);
%let _guard = %eval (&_guard+1);
%if &_guard > 1000 %then %let _position = 0;
%end;
%syscall prxfree(_tokenRx);
%superq(_result)
%mend;
以下是应用于模板化SQL查询的解析器(已调整为Proc SQL)。
%let myQuery = %str(
DROP TABLE this
;
INSERT INTO SomeTable /* sas insert syntax */
SELECT * FROM OtherTable
WHERE ${field} = ${target}
;
UPDATE foo
SET x = 1
WHERE
field = ${anotherVariable}
;
);
%let field = name;
%let target = 'Jane';
%let myVariable = XYZ;
%let anotherVariable = 'John';
%put %resolver (%superq(myQuery));
proc sql;
create table this (id int);
create table SomeTable like sashelp.class;
create table OtherTable as select * from sashelp.class;
create table foo as select name as field, 0 as x from sashelp.class;
%unquote(%resolver(%superq(myQUery)))
quit;