BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
David_Billa
Rhodochrosite | Level 12

When I execute the following code, it's works for first iteration and it's throwing an error from second iteration. I believe the issue is in the index portion (proc contents and data _null_). It's not working after first iteration. May be code placement is not right. Any help?

 

%macro simple_loop;
proc sql noprint;
  
    connect using &db_lib as database;

    %do type_id=1 %to %sysfunc(countw(&type_list,,s));
/*some macro code*/
 execute(
        create or replace tbl &schema_temp..&prompt_tbl_name as
          select distinct &current_distinct_var_list
          from &schema_temp..&source_tbl
        ;
      ) by database;
      
      
      create tbl &prompt_tbl_name as
        select * from connection to database (
          select *
          from &schema_temp..&prompt_tbl_name;
        )
      ;
proc contents data=&prompt_tbl_name noprint
out=index_list(keep=libname memname name);
run;

filename code temp;
data _null_;
set index_list;
by libname memname ;
file code;
if first.libname then put 'proc datasets nolist lib=' libname ';' ;
if first.memname then put 'modify ' memname ';' / '  create index ' @;
put name @;
if last.memname then put ';' / 'run;' ;
if last.libname then put 'quit;' ;
run;  
%include code / source2;     
%end;    
quit;

%mend simple_loop;
%simple_loop;
1 ACCEPTED SOLUTION

Accepted Solutions
yabwon
Amethyst | Level 16

try this:

%macro simple_loop;

%do type_id=1 %to %sysfunc(countw(&type_list,,s));

  proc sql noprint;
    
  connect using &db_lib as database;

  /*some macro code*/
   execute(
          create or replace tbl &schema_temp..&prompt_tbl_name as
            select distinct &current_distinct_var_list
            from &schema_temp..&source_tbl
          ;
        ) by database;
        
        
        create tbl &prompt_tbl_name as
          select * from connection to database (
            select *
            from &schema_temp..&prompt_tbl_name;
          )
        ;
  quit;

  proc contents data=&prompt_tbl_name noprint
  out=index_list(keep=libname memname name);
  run;

  filename code temp;
  data _null_;
  set index_list;
  by libname memname ;
  file code;
  if first.libname then put 'proc datasets nolist lib=' libname ';' ;
  if first.memname then put 'modify ' memname ';' / '  create index ' @;
  put name @;
  if last.memname then put ';' / 'run;' ;
  if last.libname then put 'quit;' ;
  run;  
  %include code / source2;     
%end;    

%mend simple_loop;
%simple_loop;

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



View solution in original post

9 REPLIES 9
yabwon
Amethyst | Level 16

Before running the code add:

options mprint symbolgen;

to it and share log results. 

 

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



David_Billa
Rhodochrosite | Level 12

@yabwon Log is shown below. It's big file hence I shared only the portion of error log. Here the catch is index is created for all the iterations and from second iteration I could see the error before the index steps. However if I remove the index part from my code, it is executing without any issues for all the iteration.

 

SYMBOLGEN:  Macro variable CLASS_VAR_ID resolves to 2
MLOGIC(SIMPLE_LOOP):  %IF condition (&class_var_ID eq 1) is FALSE
MLOGIC(SIMPLE_LOOP):  %LET (variable name is PROMPT_TBL_NAME)
SYMBOLGEN:  Macro variable PROMPT_TBL_NAME resolves to dmm_tts_pt_div
SYMBOLGEN:  Macro variable CURRENT_CLASS_VAR resolves to upn
MLOGIC(SIMPLE_LOOP):  %DO loop index variable CLASS_VAR_ID is now 3; loop will not iterate again.
MLOGIC(SIMPLE_LOOP):  %PUT NOTE: &=prompt_TBL_name
SYMBOLGEN:  Macro variable PROMPT_TBL_NAME resolves to dmm_ttt_pt_div_upn
NOTE: PROMPT_TBL_NAME=dmm_ttt_pt_div_upn
NOTE: Line generated by the invoked macro "SIMPLE_LOOP".
235                  execute(         create or replace TBL &schema_temp..&prompt_TBL_name as           select distinct
                     -------
                     180
235  ! &current_distinct_var_list           from &schema_temp..&source_TBL         ;       ) by database;
SYMBOLGEN:  Macro variable SCHEMA_TEMP resolves to PMQ_TEMP_TBLS
SYMBOLGEN:  Macro variable PROMPT_TBL_NAME resolves to dmm_tts_pt_div_upn
SYMBOLGEN:  Macro variable CURRENT_DISTINCT_VAR_LIST resolves to bss_division,upn
SYMBOLGEN:  Macro variable SCHEMA_TEMP resolves to PMQ_TEMP_TBLS
SYMBOLGEN:  Macro variable SOURCE_TBL resolves to dmm_transfer_prompts
MPRINT(SIMPLE_LOOP):   execute( create or replace TBL PMQ_TEMP_TBLS.dmm_tts_pt_div_upn as select distinct bss_division,upn 
from PMQ_TEMP_TBLS.dmm_transfer_prompts ;
ERROR 180-322: Statement is not valid or it is used out of proper order.
NOTE: Line generated by the invoked macro "SIMPLE_LOOP".
235                  execute(         create or replace TBL &schema_temp..&prompt_TBL_name as           select distinct
235  ! &current_distinct_var_list           from &schema_temp..&source_TBL         ;       ) by database;
                                                                                             -
                                                                                             180
ERROR 180-322: Statement is not valid or it is used out of proper order.
MPRINT(SIMPLE_LOOP):   ) by database;

 

yabwon
Amethyst | Level 16

There is this very old saying which states: >>Usually a code executed inside the Proc SQL works better if before it you write "Proc SQL;"...<< 

 

Look at your code, where the %do-loop is located and what it contains, you have: 

 

1) "proc SQL"

2) "%do-loop"

3) "sql code"

4) "proc contents"

5) "data step"

6) "%include with proc datasets"

7) "%end" for do-loop

😎 "quit;"

 

Basically point 4) turns off proc SQL and in the second iteration of %do-loop tries to execute "sql code" without Proc SQL... 

 

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



David_Billa
Rhodochrosite | Level 12

Thanks for the insights. Were you able to help me fix the issue? I'm not certain how to replace proc contents

yabwon
Amethyst | Level 16

try this:

%macro simple_loop;

%do type_id=1 %to %sysfunc(countw(&type_list,,s));

  proc sql noprint;
    
  connect using &db_lib as database;

  /*some macro code*/
   execute(
          create or replace tbl &schema_temp..&prompt_tbl_name as
            select distinct &current_distinct_var_list
            from &schema_temp..&source_tbl
          ;
        ) by database;
        
        
        create tbl &prompt_tbl_name as
          select * from connection to database (
            select *
            from &schema_temp..&prompt_tbl_name;
          )
        ;
  quit;

  proc contents data=&prompt_tbl_name noprint
  out=index_list(keep=libname memname name);
  run;

  filename code temp;
  data _null_;
  set index_list;
  by libname memname ;
  file code;
  if first.libname then put 'proc datasets nolist lib=' libname ';' ;
  if first.memname then put 'modify ' memname ';' / '  create index ' @;
  put name @;
  if last.memname then put ';' / 'run;' ;
  if last.libname then put 'quit;' ;
  run;  
  %include code / source2;     
%end;    

%mend simple_loop;
%simple_loop;

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



Kurt_Bremser
Super User

Your first statement created by the %DO loop is a PROC SQL statement (EXECUTE), but your loop also contains a PROC CONTENTS, which implicitly terminates your PROC SQL right there.

David_Billa
Rhodochrosite | Level 12

Yes I did this with one iteration before placing my code inside macro. I didn't realise that it will fail in macro looping. Now I'm not sure to correct it inside macro 

Kurt_Bremser
Super User

That's why you need to first get a complete second iteration of the intended loop to run before coding the macro. Only then will you see which components MUST be inside the loop.

hackathon24-white-horiz.png

The 2025 SAS Hackathon has begun!

It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.

Latest Updates

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 9 replies
  • 2159 views
  • 5 likes
  • 3 in conversation