%macro useList(var,icd); proc sql noprint; select quote(trim(&var.)) into: &var.list separated by ',' from out.ped where not missing (&var.); quit; if dx in: (&&&var.list) then &icd = '1'; %mend; %useList(code);
I got this to work by making codelist a global variable but I want to understand what is happening.
If you assign a value to a macro variable while a MACRO is executing (like your use of the INTO syntax of PROC SQL) and the macro variable does not already exist then it will be created as LOCAL to the macro. Once the macro finishes running any LOCAL macro variables it has defined no longer exist.
If you want to be able to use the macro variable after the macro finishes running then you could either force it into the GLOBAL scope by adding at %GLOBAL statement. Make sure there is not already a macro variable with that name!
%macro useList(var,icd); %if not %symexist(&var.list) %then %global &var.list ; ...
Or just make sure the macro variable exists before you call the macro.
%let codelist=; %useList(code)
Also the SELECT statement will not create the macro variable when no observations meet the condition. You should probably set the macro variable to some default value before the SELECT statement to insure that an old value is not re-used.
%let &var.list=; select .... into :&var.list ...
PS Your macro as written will generate invalid SAS code. You cannot have an IF statement outside of a DATA step. And you could not call the macro inside of a data step because it generates a PROC step that would immediately end the definition of the data step.