Hello all,
I'm working with SAS9.4.
Can anyone explain why when using a string derived using CATS in a call to %nrquote, I get an error, but only when assigning the value to a macro variable via %LET?
Strangely, if I replace the %LET with a %PUT, the code succeeds.
Not sure if this is a bug or an expected behaviour.
If you run the code below from EG you'll see what I mean.
%let run_date= "31Jan2015:00:00:00"dt;
data _null_;
date=datepart(&run_date);
y=cats(year(date));
y2=cats('20','15');
y3=strip(year(date));
call symput('YEAR', y);
call symput('YEAR2', y2);
call symput('YEAR3', y3);
run;
/*fails*/
%let SYSLAST = %nrquote(DATASET_&YEAR);
%let SYSLAST = %nrquote(DATASET_&YEAR2);
/*succeeds*/
%let SYSLAST = %nrquote(DATASET_&YEAR3);
%put SYSLAST = %nrquote(DATASET_&YEAR3);
The datastep is user-written precode to a DI job and the SYSLAST assignment is auto-generated. I was tasked with troubleshooting and resolving the issue. I got as far as understanding how to avoid the issue, but I can't explain the cause.
All help is welcomed.
Thanks,
Ben
In your data step the only difference in your three variables is the default length that SAS will use to create them. Since you didn't tell SAS in advance what length to make the variables it will guess based on what it sees on the right hand side of the assignment statement.
The first thing you should change is to use CALL SYMPUTX() instead of the older CALL SYMPUT() this will automatically remove the trailing blanks from the value before creating the macro variable.
The real problem with your code is that you are attempting to use the macro quoting function in the value you are setting to a SAS system option. SYSLAST is not just a macro variable, it is also the _LAST_ system option. If you try to insert macro quotation marks into that value you will have created an invalid membername.
In your data step the only difference in your three variables is the default length that SAS will use to create them. Since you didn't tell SAS in advance what length to make the variables it will guess based on what it sees on the right hand side of the assignment statement.
The first thing you should change is to use CALL SYMPUTX() instead of the older CALL SYMPUT() this will automatically remove the trailing blanks from the value before creating the macro variable.
The real problem with your code is that you are attempting to use the macro quoting function in the value you are setting to a SAS system option. SYSLAST is not just a macro variable, it is also the _LAST_ system option. If you try to insert macro quotation marks into that value you will have created an invalid membername.
Thanks for unravelling my problem Tom. Well explained and resolved!
If I'd replaced the _null_ with a physical dataset, I would have seen the variation in variable lengths from the dataset properties and potentially found the problem myself. I'll try this the next time I get a seemingly "invisble" problem.
This is how the code looks after incorporating your suggestions.
%let run_date= "31Jan2015:00:00:00"dt; data _null_; length y $4; date=datepart(&run_date); y=year(date); call symputx('YEAR', y); run; %let SYSLAST = %nrquote(DATASET_&YEAR);
But why are you using %NRQUOTE() macro function? it is not doing anything in that situation. The result is the same as if you just did:
%let syslast=DATASET_&year ;
Try this to see that the %NRQUOTE() function is not having any impact.
data year1 year2;
year=1; output year1;
year=2; output year2;
run;
%let year=1;
%let syslast=%nrquote(YEAR&year);
%let year=2;
data _null_;
set;
put year=;
run;
data _null_;
set &syslast;
put year=1;
run;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 16. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.