带你读《SAS数据分析开发之道 软件质量的维度》第三章通信交流3.2系统数字返回码(四)

&SQLRC

&SQLRC自动宏变量功能与 &SYSERR相似,但不同之处在于,&SQLRC适用于 SAS程序及 DATA步骤,仅表示SQL程序中最近运行的 SQL程序指令的状态。需要注意的是,&SQLRC仅在 SQL程序指令之后重置,而不是SQL程序——每一个程序都包含多个 SQL程序指令。与 &SYSERR不同,&SQLRC是可读写的,若在同一个SQL程序内被多次评估,则需要重置为“0”。然而,由于&SQLRC未超出 SQL程序边界,因此,在 SQL程序内的第一个 SQL程序指令之前,&SQLRC无须重置为“0”。

以下输出信息的目的是确定数据集中观测数据的数量,但由于 Original数据集不存在,因此目的未能达成。需要注意的是,由于&SYSCC是可读写的,也是可累积的,因此,它必须重置为0,然而,&SQLRC在单独使用时则无须进行重置。另外还需要注意,&SQLRC值为8表示的是SQL执行过程中的一般性错误 :

%letsyscc=0;

 

procsqlnoprint;selectcount(*)into:obstotfromoriginal;

quit;

ERROR:TableWORK.ORIGINALdoesn’thaveanycolumns.PROCSQLrequireseachofitstablestohaveatleast1column.

 

%putSYSERR:&syserr;SYSERR:1012

%putSYSCC:&SYSCC;SYSCC:1012


 

 

 

%putSQLRC:&SQLRC;

SQLRC:8

 

&SQLRC的一个特性是在每个 SQL 程序指令之后都需要对它进行重置,即便是在同一个 SQL程序内,也需要重置。由于一个 SQL程序中包含多个 SQL程序指令, 因此,如果在 SQL程序结束时评估 &SQLRC,它将反映的是最近一个程序指令的成败。在下面代码中,由于 Nodatanodatanodata数据集不存在,因此,第一个 SQL程序指令未能正常运行,&SQLRC暂时设置为“8”:

datatemp;

lengthchar1$10;run;

 

%letsyscc=0;procsqlnoprint;

selectcount(*)into:obstot1

fromnodatanodatanodata;*datasetdoesnotexist*;

%putSQLRC:&sqlrc;

%putSYSCC:&syscc;selectcount(*)into:obstot2fromtemp;

quit;

%putSQLRC:&sqlrc;

%putSYSCC:&syscc;

 

由于第二个 SQL程序指令顺利运行,&SQLRC又从 8重置为 0,从而掩盖了上一个错误。此外,&SYSCC 仅在步骤边界之后设置,因此,在故障后面(但在 QUIT程序指令之前)的&SYSCC值会误保留为“0”。直到在QUIT之后,&SYSCC才能正确地反映出前一个 SQL程序指令的错误 :

%letsyscc=0;procsqlnoprint;

selectcount(*)into:obstot1

fromnodatanodatanodata;*datasetdoesnotexist*;


ERROR:FileWORK.NODATANODATANODATA.DATAdoesnotexist.

%putSQLRC:&sqlrc;SQLRC:8

%putSYSCC:&syscc;

SYSCC:0

selectcount(*)into:obstot2fromtemp;

quit;

%putSQLRC:&sqlrc;SQLRC:0

%putSYSCC:&syscc;

SYSCC:1012

 

如上所述,&SYSCC能检测到包含单个或多个程序指令的SQL程序中的故障,但 &SYSCC无法分离出 SQL 程序中发出警告或“运行时错误”的位置。因此,为了更明确地评估多指令的 SQL程序,可以评估每个 SQL程序指令之后的 &SQLRC。

 

&SYSFILRC

自动宏变量 &SYSFILRC表示最近 FILENAME程序指令的顺利运行或故障,若FILENAME运行正确,则&SYSFILRC为“0”。在另一本书中讲到的一样, FILENAME        程序指令的一个用途是评估某个数据集是否被其他用户或过程锁定。以下代码能确定    WORK.Temp    数据集中保存的是共享锁定还是排他锁定。如果没有锁 定,那么数据集可以随意获取使用 :

datatemp;

lengthchar$10;run;

 

%letsyscc=0;

%letlib=work;

%lettab=temp;

%letfil=%sysfunc(pathname(&lib))\&tab..sas7bdat;filenamemyfile"&fil";

data_null_;


excl=fopen('myfile','U');

ifexcl=1thencallsymput('LOCK','None');

elsedo;

shared=open("&lib..&tab");

ifshared=1thencallsymput('LOCK','Shared');elsecallsymput('LOCK','Exclusive');

end;

run;

%putLOCK:&lock;

%putSYSFILRC:&sysfilrc;

%putSYSCC:&syscc;

 

在运行过程中,FILENAME程序指令顺利进行&SYSFILRC0,且数据集没有被锁定&LOCKNone。如果Temp数据集不存在,也未出现“运行时错,但&SYSFILRC会设置为“1以反映FILENAME程序指令中存在一个异常情况。以下输出信息进一步说明 &SYSCC的值没有受到 &SYSFILRC或其他文件丢失的影响 :

%putLOCK:&lock;LOCK:None

%putSYSFILRC:&sysfilrc;

SYSFILRC:1

%putSYSCC:&syscc;

SYSCC:0

 

由于未检查 &SYSFILRC,输出信息错误地显示 Temp数据集中没有锁定,其实数据集并不是没有锁定,而是丢失了。当 FILENAME程序指令出现异常情况时,FOPEN函数会创建Temp.sas7bdat文件,该文件反过来也会(通过 OPEN功能)显示为未锁定状态。这显示了 &SYSFILRC在 FILENAME引用一个丢失文件时的一个重要特点,即生成一个返回码“1”,但是,生成的文件参考是有效的,其一旦被 FOPEN      引用,就会创建出已丢失的文件。这种循环逻辑是非常有必要的,由于要从头开始创建丢失的文件,因此,FOPEN需要一个 FILENAME程序指令生成的有效文件参考。“互斥和信号量”部分会进一步解释逻辑错误的必要性。

若在 FILENAME程序指令之后立即评估&SYSFILRC,便会阻止 FOPEN执行并产生这一故障,而且,尽管创建的文件(Temp.sas7bdat)目前确实出现在 WORK文件库中,但它实际并不是一个真实存在的 SAS数据集,因此,它不能在SAS中打开或删除,只能通过 OS删除。

FILENAME程序指令的另一个常见用途是创建连接 OS的管道命令, 但是,&SYSFILRC   宏变量此时是以不同的方式运行的。在下面的代码中,%GET_FILELIST宏接受一个参数化的文件内容目录,并创建一个空格分隔的宏变量(&FILELIST),该变量包含该文件内容目录中的所有文件。这是一个非常有效的工具,然而,如下面    的输出所示,若参数中指定一个不存在的文件内容目录(C:\neverland),那么这一异常情况会出现在SAS日志中,而不会显示在&SYSFILRC中,&SYSFILRC值为“0”则表示“顺利运行”:

%macroget_filelist(dir=);

%letsyscc=0;

%locali;

%localfil;

%globalfilelist;

%letfilelist=GENERALERROR;filenamefpipe"dir/b&dir*.sas";data_null_;

length filelist $10000;infileftruncover;inputfilename$100.;

filelist=catx('',filelist,filename);callsymput('filelist',filelist);retainfilelist;

run;

%mend;

 

%get_filelist(dir=c:\neverland\);

 

NOTE:TheinfileFis:

UnnamedPipeAccessDevice,

PROCESS=dir/bc:\neverland\*.sas,RECFM=V,

LRECL=32767

 

Stderroutput:


The system cannot find the file specified.NOTE:0recordswerereadfromtheinfileF.

NOTE:DATAstatementused(Totalprocesstime):realtime   0.05seconds

cputime               0.01seconds

 

264  %putSYSCC:&syscc;SYSCC:0

265  %putSYSERR:&syserr;SYSERR:0

266  %putSYSFILRC:&sysfilrc;

SYSFILRC:0

 

为了克服 &SYSFILRC的这一缺点,首先需要使用一个不包含PIPE命令的FILENAME   程序指令证实文件内容目录的存在,只有确认了该文件目录的存在,才能发布第二个包含 PIPE命令的 FILENAME程序指令。

上一篇:2021-04-28 AIstduio & google colab pro上手


下一篇:一键安装常用服务-lnmp等等