Parameters SAS的宏参数中会丢失换行符

Parameters SAS的宏参数中会丢失换行符,parameters,sas,macros,Parameters,Sas,Macros,我想将包含换行符的文本从SAS表传输到外部数据库表(通过ODBC)。 我使用宏变量作为缓冲区。我使用宏将文本插入表中 远程数据库的。问题是文本中的换行符丢失了, 如果我将文本作为参数传递给宏。 我怎样才能保持线路中断 %macro dbinsert (id=,text=); /* Macro for inserting text into table of second database. For test purposes, odbc table replaced with SAS

我想将包含换行符的文本从SAS表传输到外部数据库表(通过ODBC)。 我使用宏变量作为缓冲区。我使用宏将文本插入表中 远程数据库的。问题是文本中的换行符丢失了, 如果我将文本作为参数传递给宏。 我怎样才能保持线路中断

%macro dbinsert (id=,text=);
/*
   Macro for inserting text into table of second database.
   For test purposes, odbc table replaced with SAS table.
   Issue: line breaks will be lost. How can i keep the line breaks?

   Original Code:
      proc sql;
         CONNECT TO ODBC (DSN="mydb");
         EXEC (update mytable
            set text= "&text."
            where id = &id.;
            ) BY ODBC;
      quit;
*/
   proc sql noprint;
       update x2
       set text = "&text."
       where id = &id.;
   quit;

%mend dbinsert;

%macro main;

/* Initialize SAS table. Just for test purposes. */
data x1;
   text="Hello Martin how are you?"; output;
   text="Thank you I am fine!"; output;
   text="And how are you?"; output;
run;

/* Read content from SAS table into macro variable (text1). The content is separated via line breaks 0D0A. */
proc sql noprint;
   select text into :text1 separated by '0D0A'x from x1;
quit;

/* Initialize table in second database. Just for test purposes. */
data x2;
   length id 8 text $200;
   id=1; text="111"; output;
   id=2; text="222"; output;
run;

%dbinsert(id=2,text=&text1.);

%mend main;
%main;

宏不支持不可打印的字符

data _null_;
  call symputx('text',quote(symget('text'),"'"));
run;
从文件



SAS宏语言是一种基于字符串的语言。它不支持使用十六进制字符常量


注意:SAS宏语言不支持使用十六进制值指定不可打印的字符。



宏变量值的最大长度为65534个字符。宏变量的长度由指定给它的文本决定,而不是由特定的长度声明决定。因此,它的长度随包含的每个值而变化。宏变量只包含字符数据。但是,宏工具具有一些功能,当变量包含可解释为数字的字符数据时,可以将其作为数字进行计算。宏变量的值将保持不变,直到具体更改为止。宏变量独立于SAS数据集变量


注意:只能将可打印字符指定给宏变量。分配给宏变量的不可打印值可能导致不可预测的结果。
可能的替代方案

你知道EXEC和pass-through,很好

考虑使用SQL为串联字符串文字的字符串表达式构建源代码。表达式将包含使用远程数据库本机字符函数的源代码。必须修改
DBINSERT
宏以处理现在包含表达式的参数

同样,宏会将不可打印的字符转换为空格,因此如果
x1.text
中的数据值包含嵌入的CRLF,则它们不会出现在构造的表达式中

例如:

重要提示:请勿将此版本的DBINSERT与不受信任的用户提供的任何输入或WEB输入一起使用。来自数据值的Codegen是SQL注入或代码注入的向量

%macro dbinsert (id=,expression=);
   proc sql noprint;
       update x2
       set text = &expression
       where id = &id.;
   quit;
%mend dbinsert;

data x1;
   text="Hello Martin how are you?"; output;
   text="Thank you I am fine!"; output;
   text="And how are you?"; output;
run;

/*
 * CONSTRUCT SOURCE CODE FOR AN EXPRESSION THAT CONCATENTATES STRING LITERALS
 * (also known as codegen short for code generator)
 */
proc sql noprint;
  select 
    quote(trim(text)) 
    into :text1 
    separated by '||byte(13)||byte(10)||' 
    from x1;

data x2;
   length id 8 text $200;
   id=1; text="111"; output;
   id=2; text="222"; output;
run;

options mprint;
%dbinsert(id=2,expression=&text1.);
%symdel text1;

title;
ods html style=monospace;
proc print data=x2; where id=2; 
proc print data=x2; where id=2; format text $HEX400.;
proc print data=x2; where id=2; 
  var text / style=[asis=true];
run;
ods html close;
调用
DBINSERT
时显示codegen运行的日志

634  %dbinsert(id=2,expression=&text1.);
MPRINT(DBINSERT):   proc sql noprint;
MPRINT(DBINSERT):   update x2 set text = "Hello Martin how are you?"||byte(13)||byte(10)||"Thank
you I am fine!"||byte(13)||byte(10)||"And how are you?" where id = 2;
NOTE: 1 row was updated in WORK.X2.
检查结果。SAS ViewTable将不可打印的内容呈现为空格,但控制字符位于数据值中

在查看器中显示结果的图像

在ODS HTML中的结果相同,第二个表显示十六进制格式时的文本值。第三个表显示了当样式选项
ASIS=YES
生效时,查看由
ODS HTML
解释的控制字符


宏不支持不可打印的字符

data _null_;
  call symputx('text',quote(symget('text'),"'"));
run;
从文件



SAS宏语言是一种基于字符串的语言。它不支持使用十六进制字符常量


注意:SAS宏语言不支持使用十六进制值指定不可打印的字符。



宏变量值的最大长度为65534个字符。宏变量的长度由指定给它的文本决定,而不是由特定的长度声明决定。因此,它的长度随包含的每个值而变化。宏变量只包含字符数据。但是,宏工具具有一些功能,当变量包含可解释为数字的字符数据时,可以将其作为数字进行计算。宏变量的值将保持不变,直到具体更改为止。宏变量独立于SAS数据集变量


注意:只能将可打印字符指定给宏变量。分配给宏变量的不可打印值可能导致不可预测的结果。
可能的替代方案

你知道EXEC和pass-through,很好

考虑使用SQL为串联字符串文字的字符串表达式构建源代码。表达式将包含使用远程数据库本机字符函数的源代码。必须修改
DBINSERT
宏以处理现在包含表达式的参数

同样,宏会将不可打印的字符转换为空格,因此如果
x1.text
中的数据值包含嵌入的CRLF,则它们不会出现在构造的表达式中

例如:

重要提示:请勿将此版本的DBINSERT与不受信任的用户提供的任何输入或WEB输入一起使用。来自数据值的Codegen是SQL注入或代码注入的向量

%macro dbinsert (id=,expression=);
   proc sql noprint;
       update x2
       set text = &expression
       where id = &id.;
   quit;
%mend dbinsert;

data x1;
   text="Hello Martin how are you?"; output;
   text="Thank you I am fine!"; output;
   text="And how are you?"; output;
run;

/*
 * CONSTRUCT SOURCE CODE FOR AN EXPRESSION THAT CONCATENTATES STRING LITERALS
 * (also known as codegen short for code generator)
 */
proc sql noprint;
  select 
    quote(trim(text)) 
    into :text1 
    separated by '||byte(13)||byte(10)||' 
    from x1;

data x2;
   length id 8 text $200;
   id=1; text="111"; output;
   id=2; text="222"; output;
run;

options mprint;
%dbinsert(id=2,expression=&text1.);
%symdel text1;

title;
ods html style=monospace;
proc print data=x2; where id=2; 
proc print data=x2; where id=2; format text $HEX400.;
proc print data=x2; where id=2; 
  var text / style=[asis=true];
run;
ods html close;
调用
DBINSERT
时显示codegen运行的日志

634  %dbinsert(id=2,expression=&text1.);
MPRINT(DBINSERT):   proc sql noprint;
MPRINT(DBINSERT):   update x2 set text = "Hello Martin how are you?"||byte(13)||byte(10)||"Thank
you I am fine!"||byte(13)||byte(10)||"And how are you?" where id = 2;
NOTE: 1 row was updated in WORK.X2.
检查结果。SAS ViewTable将不可打印的内容呈现为空格,但控制字符位于数据值中

在查看器中显示结果的图像

在ODS HTML中的结果相同,第二个表显示十六进制格式时的文本值。第三个表显示了当样式选项
ASIS=YES
生效时,查看由
ODS HTML
解释的控制字符


不必尝试添加将宏变量的值转换为有效代码所需的引号,只需编写宏,假设该值已经是要包含在生成代码中的有效语法即可。那么SQL语法就是:

set text = &text.
然后,如果需要添加远程系统用于在字符串中指定特殊字符的任何语法,您可以使用

%dbinsert (id=,text='ABC'||byte(13)||'XYZ')
如果您有一个现有的宏变量,并且希望将其括在单引号中,则可以使用数据步骤来保留任何特殊字符