I am trying to create array that hold a value.
proc sql noprint;
select count(*) into :dscnt from study;
select libname into :libname1 - :libname&dscnt from study;
quit;
I think the syntax is correct but i keep getting this following error message in in SAS studio.
***NOTE: PROC SQL set option NOEXEC and will continue to check the syntax of statements.
NOTE: Line generated by the macro variable "DSCNT".
79 libname 4
_
22
200
ERROR 22-322: Syntax error, expecting one of the following: ',', FROM, NOTRIM.
ERROR 200-322: The symbol is not recognized and will be ignored.***
Can someone explain to me what i am doing wrong?
Thanks
You do not need to know the number of items ahead of time, if you leave it blank, SAS will automatically create the correct number of macro variables.
If you do want to use that number elsewhere you can create it using the TRIMMED option to remove any extra spaces. See the second example below.
proc sql noprint;
select name into :name1- from sashelp.class;
quit;
%put &name1;
%put &name19.;
proc sql noprint;
select count(distinct name) into :name_count TRIMMED from sashelp.class;
quit;
%put &name_count;
Results:
3068 proc sql noprint;
3069 select name into :name1- from sashelp.class;
3070 quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds
3071
3072 %put &name1;
Alfred
3073 %put &name19.;
William
3074
3075 proc sql noprint;
3076 select count(distinct name) into :name_count TRIMMED from
3076! sashelp.class;
3077 quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.01 seconds
cpu time 0.00 seconds
3078
3079 %put &name_count;
19
The into syntax in proc sql stores formatted values into macro variables. For example if you run this code:
proc sql noprint;
select count(*) into :dscnt from sashelp.class;
quit;
%put #&dscnt#;
You will see the output is:
# 19#
In otherwords the result is left padded with spaces. This means in your example, the code is resolving to something like:
select libname into :libname1 - :libname 19 from study;
^ Which is obviously invalid syntax. To fix this, you can simply add the TRIMMED keyword to your SQL statement:
select count(*) into :dscnt TRIMMED from study;
Thanks to Reeza for the TRIMMED keyword.
do something like below
proc sql noprint;
select count(*) into :dscnt from sashelp.class;
select name into :name1 - :name%left(&dscnt) from sashelp.class;
quit;
Related
I am trying to select a large number of files using the proc sql statement below
proc sql;
select cats(libname, ".",memname) into :names separated by " "
from dictionary.tables
where upcase(libname) = "MYLIBNAME";
quit;
but when I write %PUT Data sets: &names; nothing appears in the log file and I get an error saying the macro names is not resolved. Any ideas what is going wrong here?
MYLIBNAME is an invalid libref. Librefs have a maximum of 8 characters. MYLIBNAME is 9 characters so there will be no librefs defined in your SAS session that can match it.
What happens if you try libname = "WORK" or libname = "SASHELP" ? Macro variable names will get populated.
Be careful with libraries containing many thousands of tables. A macro variable can only be 64K-2 characters long.
#Richard answer is perfect. if it is still not working do the following.
try outobs =1, just to check with and without where clause
proc sql outobs= 1;
select cats(libname, ".",memname) into :names separated by " "
from dictionary.tables
where upcase(libname) = "SASHELP";
quit;
%put &names;
use proc contents, followed by concatenation. it will show error in next step, if your macro variable is longer than 65534
PROC CONTENTS DATA=SASHELP._ALL_ out= new(keep=memname libname) noprint; RUN
proc sql;
select cats(libname, ".",memname) into :names separated by " "
from new;
I want to produce a macro that converts the variable names of a dataset into the variables' labels. I intend to apply this macro for large datasets where manually changing the variable names would be impractical.
I came across this code online from the SAS website, which looked promising but produced errors. I made slight edits to remove some errors. It now works for their sample dataset but not mine. Any assistance with improving this code to work with my sample dataset would be greatly appreciated!
SAS sample dataset (works with code):
data t1;
label x='this_x' y='that_y';
do x=1,2;
do y=3,4;
z=100;
output;
end;
end;
run;
My sample dataset (does not work with code):
data t1;
input number group;
label number = number_lab group = group_lab;
datalines;
1 1
1 .
2 1
2 .
3 2
3 .
4 1
4 .
5 2
5 .
6 1
6 .
;
run;
Code:
%macro chge(dsn);
%let dsid=%sysfunc(open(&dsn));
%let cnt=%sysfunc(attrn(&dsid,nvars));
%do i= 1 %to &cnt;
%let var&i=%sysfunc(varname(&dsid,&i));
%let lab&i=%sysfunc(varlabel(&dsid,&i));
%if lab&i = %then %let lab&i=&&var&i;
%end;
%let rc=%sysfunc(close(&dsid));
proc datasets;
modify &dsn;
rename
%do j = 1 %to &cnt;
%if &&var&j ne &&lab&j %then %do;
&&var&j=&&lab&j
%end;
%end;
quit;
run;
%mend chge;
%chge(t1)
proc contents;
run;
My code produces the following error messages:
ERROR 73-322: Expecting an =.
ERROR 76-322: Syntax error, statement will be ignored.
Mainly you are not closing the RENAME statement with a semi-colon. But it also looks like you have the RUN and QUIT statements in the wrong order.
But note that there is no need for that complex %sysfunc() macro code to get the list of names and labels. Since you are already generating a PROC DATASETS step your macro can generate other SAS code also. Then your macro will be clearer and easier to debug.
%macro chge(dsn);
%local rename ;
proc contents data=&dsn noprint out=__cont; run;
proc sql noprint ;
select catx('=',nliteral(name),nliteral(label))
into :rename separated by ' '
from __cont
where name ne label and not missing(label)
;
quit;
%if (&sqlobs) %then %do;
proc datasets nolist;
modify &dsn;
rename &rename ;
run;
quit;
%end;
%mend chge;
If the list of rename pairs is too long to fit into a single macro variable then you could resort to generating two series of macro variables using PROC SQL and then add back your %DO loop.
Here is SAS log from testing on your sample file.
4156 %chge(t1);
MPRINT(CHGE): proc contents data=t1 noprint out=__cont;
MPRINT(CHGE): run;
NOTE: The data set WORK.__CONT has 2 observations and 41 variables.
NOTE: PROCEDURE CONTENTS used (Total process time):
real time 0.08 seconds
cpu time 0.01 seconds
MPRINT(CHGE): proc sql noprint ;
MPRINT(CHGE): select catx('=',nliteral(name),nliteral(label)) into :rename
separated by ' ' from __cont where name ne label and not missing(label) ;
MPRINT(CHGE): quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.04 seconds
cpu time 0.00 seconds
MPRINT(CHGE): proc datasets nolist;
MPRINT(CHGE): modify t1;
MPRINT(CHGE): rename group=group_lab number=number_lab ;
NOTE: Renaming variable group to group_lab.
NOTE: Renaming variable number to number_lab.
MPRINT(CHGE): run;
NOTE: MODIFY was successful for WORK.T1.DATA.
MPRINT(CHGE): quit;
NOTE: PROCEDURE DATASETS used (Total process time):
real time 0.12 seconds
cpu time 0.00 seconds
Note that if I now try to run it again on the modified dataset it does not rename anything.
4157 %chge(t1);
MPRINT(CHGE): proc contents data=t1 noprint out=__cont;
MPRINT(CHGE): run;
NOTE: The data set WORK.__CONT has 2 observations and 41 variables.
NOTE: PROCEDURE CONTENTS used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
MPRINT(CHGE): proc sql noprint ;
MPRINT(CHGE): select catx('=',nliteral(name),nliteral(label)) into :rename
separated by ' ' from __cont where name ne label and not missing(label) ;
NOTE: No rows were selected.
MPRINT(CHGE): quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.08 seconds
cpu time 0.00 seconds
you're missing a semi-colon here:
&&var&j=&&lab&j
if you still get an error, turn on these options and let us know where the error occurs.
options symbolgen mprint;
Could anyone please tell the difference between table and tables in Proc freq with an example?
proc freq data= want;
table variable;
run;
proc freq data= want;
tables variable;
run;`
There is no difference. The statement is the TABLES statement, but SAS will silently accept TABLE as a synonym without issuing any warning or note. Some miss spellings will generate just a warning while others will cause an error.
1668 proc freq data= sashelp.class;
1669 tablex age name;
------
1
WARNING 1-322: Assuming the symbol TABLE was misspelled as tablex.
1670 run;
NOTE: There were 19 observations read from the data set SASHELP.CLASS.
1671
1672 proc freq data= sashelp.class;
1673 tabl age name;
----
1
WARNING 1-322: Assuming the symbol TABLE was misspelled as tabl.
1674 run;
NOTE: There were 19 observations read from the data set SASHELP.CLASS.
1675
1676 proc freq data= sashelp.class;
1677 tab age name;
---
180
ERROR 180-322: Statement is not valid or it is used out of proper order.
1678 run;
NOTE: The SAS System stopped processing this step because of errors.
I would like to create a macro that add a suffix to variable names in a dataset. below is my code:
%macro add_suffix(library=,dataset=,suffix=);
proc sql noprint;
select cat(name, ' = ', cats('&suffix.',name )) into :rename_list separated by ' ' from
dictionary.columns where libname = '&library.' and memname= '&dataset.';
quit;
proc datasets library=&library nolist nodetails;
modify &dataset;
rename &rename_list;
run;
quit;
%mend;
%add_suffix(library=OUTPUT,dataset=CA_SPREADS,suffix=CA);
It gives error messages:
NOTE: No rows were selected.
NOTE: PROCEDURE SQL used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
WARNING: Apparent symbolic reference RENAME_LIST not resolved.
NOTE: Line generated by the invoked macro "ADD_SUFFIX".
2 rename &rename_list; run;
-
22
76
NOTE: Enter RUN; to continue or QUIT; to end the procedure.
ERROR 22-322: Expecting a name.
ERROR 76-322: Syntax error, statement will be ignored.
If I put the library and dataset names in quotation mark, it works for the first block i.e. add values to string rename_list but not for the proc dataset step
Macro triggers like % and & are not honored inside of single quotes. That is why you are not getting any hits on your SQL query. There is no library name that has an & as the first character.
The reason it looked like it was sort of working is that when you use this in your SQL statement
catx('=',name,cats('&prefix.',name))
then you end up with a string like
age=&prefix.age
And that will actually work because the reference to the macro variable PREFIX will resolve when you run the RENAME statement.
You should just use double quotes instead.
%macro change_names(library=,dataset=,prefix=,suffix=);
%local rename_list;
proc sql noprint;
select catx('=',name,cats("&prefix",name,"&suffix"))
into :rename_list separated by ' '
from dictionary.columns
where libname = %upcase("&library")
and memname = %upcase("&dataset")
;
quit;
%if (&sqlobs) %then %do;
proc datasets library=&library nolist nodetails;
modify &dataset;
rename &rename_list;
run;
quit;
%end;
%else %put WARNING: Did not find any variables for &library..&dataset..;
%mend change_names;
%change_names(library=OUTPUT,dataset=CA_SPREADS,prefix=CA);
Your macro variables are not being resolved because you're wrapping them in single quotes ' rather than double quotes ".
You should uppercase the libname and memname parameters of your macro as these are always in uppercase in dictionary.columns.
Tested and works. Longer but maybe more beginner friendly approach. Input the dataset name and what suffix you want to add.
example: %add_suffix(orders, _old); /* will add _old suffix to all variables.*/
%macro Add_Suffix(Dataset, suffix);
proc contents noprint
data=work.&dataset out=sjm_tmp(keep=NAME);
run;
data sjm_tmp2;
set sjm_tmp;
foobar=cats(name, '=',NAME,'&suffix.');
run;
proc sql noprint;
select foobar into :sjm_list separated by ' ' from sjm_tmp2;
quit;
proc datasets library = work nolist;
modify &dataset;
rename &sjm_list;
quit;
proc datasets library=work noprint;
delete sjm_tmp sjm_tmp2 ;
run;
%mend Add_Suffix;
I am new to macro writing in SAS and being a proficient R user, I am having a difficult time understanding how to do things in SAS.
I am trying create a macro variable that contains the list of dates from a dataset.
My code is -
proc sql noprint;
select distinct sdate into : sdatem separated by ' '
from work.date_list;
quit;
%put &sdatem;
But when I run this code, the code is executed without any errors but the %put statement in the log prints
%put &sdatem;
and not the actual value. Any idea why this is happening? The dates are in yymmddn8. format.
The sample data I used is -
DATA compno_date_list;
INPUT compno sdate;
DATALINES;
12490 20090120
87432 20090120
24643 20090120
87432 20090119
12490 20090105
24643 20090105
;
proc print data=compno_date_list;
run;
Any help would be great! Thanks
Your input dataset should be work.compno_date_list, not work.date_list.
proc sql noprint;
select distinct sdate into : sdatem separated by ' '
from work.compno_date_list;
quit;
%put &sdatem;