Chapter 9 Interfaces to the Macro Facility

Introduction

Understanding DATA Step Interfaces to the Macro Facility

Understanding the SYMGET Function

Understanding the SYMPUT and SYMPUTX Call Routines

Understanding the CALL EXECUTE Routine

Understanding the RESOLVE Function

Using Macro Facility Features in PROC SQL

Creating and Updating Macro Variables with PROC SQL

Using the Macro Variables Created by PROC SQL

Displaying Macro Option Settings with PROC SQL and Dictionary Tables

 

Introduction

The interfaces described in this chapter provide you with a dynamic communication link between the SAS language and the macro facility. Until now, the discussion of the macro facility has emphasized the distinction between when macro language statements are resolved and when SAS language statements are resolved, and how the macro language can build SAS code and control SAS processing. With the interfaces described in this chapter, your SAS language programs can direct the actions of the macro processor.

The interfaces described in this chapter include SAS language functions and PROC SQL.

The following interfaces are not described in this chapter and are beyond the scope of this book. For further information about these topics, see Documentation in the Knowledge Base, at http://support.sas.com.

• SAS Component Language (SCL) functions and routines

• %SYSLPUT and %SYSRPUT, two macro functions that provide an interface with SAS/CONNECT

Understanding DATA Step Interfaces to the Macro Facility

Five functions and four call routines in the SAS language can interact with the macro processor during execution of a DATA step. Table 9.1 lists these nine tools.

Table 9.1 DATA step interface tools

Tool

Description

CALL SYMDEL(macro-variable<,’NOWARN’)

Deletes macro-variable from the global symbol table. The NOWARN option suppresses the SAS warning in the SAS log if macro-variable does not exist.

SYMEXIST(argument)

Determines if the macro variable specified as argument exists. SYMEXIST returns a 0 if the macro variable does not exist, and a 1 if it does.

SYMGET(argument)

Obtains the value of a macro variable specified as argument and returns this value as a character value.

SYMGLOBL(argument)

Determines if the macro variable specified as argument is global to the DATA step during execution of the DATA step. SYMGLOBL returns a 0 if the macro variable is not in the global symbol table, and a 1 if it is.

SYMLOCAL(argument)

Determines if the macro variable specified as argument is local to the DATA step during execution of the DATA step. SYMLOCAL returns a 0 if the macro variable is not in an existing local symbol table during DATA step execution, and a 1 if it is.

CALL SYMPUT(macro-variable, value)

Assigns value to macro-variable. This routine does not trim leading and trailing blanks.

CALL SYMPUTX(macro-variable, value <,symbol-table>)

Assigns value to macro-variable. This routine removes both leading and trailing blanks. Optionally, this routine can direct the macro processor to store the macro variable in a specific symbol table (G=global, L=local, and F=most local if it exists).

CALL EXECUTE(argument)

Executes the resolved value of argument. Arguments that resolve to a macro facility reference execute immediately. Arguments that resolve to SAS language statements execute after the DATA step that includes CALL EXECUTE ends.

RESOLVE(argument)

Macro facility resolves argument during DATA step execution where argument can be an expression that includes macro variables and macro program calls.

 

Understanding the SYMGET Function

The SYMGET SAS language function retrieves macro variable values from the macro symbol tables during execution of a DATA step. The SYMGET function returns a character value. With this function, you can create and update data set variables with information that the macro processor retrieves from macro variables.

A macro variable that you reference with SYMGET must exist before you apply it in a DATA step. If you create a macro variable in the same DATA step with CALL SYMPUT or CALL SYMPUTX, you can retrieve the macro variable value with SYMGET if it follows the CALL SYMPUT or CALL SYMPUTX call.

By default, SYMGET creates a character variable with a length of 200 bytes. You can specify a different length with either the LENGTH or ATTRIB statement. If the DATA step variable is defined as numeric, SAS attempts to convert the value that SYMGET retrieves to a number and writes a warning message to the SAS log.

The SYMGET function accepts three types of arguments:

• the name of a macro variable that is enclosed in single quotation marks and without the leading ampersand. In the following example, assume X is a macro variable that was defined earlier in the SAS session.

      y=symget('x'),

• the name of a DATA step character variable whose value is the name of a macro variable. (See Example 9.1 for a discussion of this code.)

%let certific=CRT283817;

%let networki=NET3UD697;

%let operatin=OPSI18375;

%let programm=PRG8361WQ;

%let software=SFT3521P8;

%let webdevel=WBD188377;

data temp;

  set books.ytdsales;

  attrib compsect length=$8 label='Section'

         sectionid length=$9 label='Section ID';

  *----Construct macro variable name by compressing

       section name and taking the first 8 characters.

       e.g. section=Programming, then COMPSECT=“Programm”;

  compsect=substr(compress(section),1,8);

  sectionid=symget(compsect);

run;

proc print data=temp;

  title “Defining the Section Identification Code”;

  var section compsect sectionid;

run;

• a DATA step character expression. The resolution of the character expression is the name of a macro variable. (See Example 9.2 for a discussion of similar code.)

%let factor1=1.10;

%let factor2=1.23;

%let factor3=1.29;

data projections;

  set books.ytdsales;

  array factor{3} factor1-factor3;

  array newprice{3} newprice1-newprice3;

  format newprice1-newprice3 dollar10.2;

  drop i;

  do i=1 to 3;

    factor{i}=input(symget(cats('factor',put(i,1.))),best8.);

    newprice{i}=factor{i}*saleprice;

  end;

run;

The next three examples illustrate the three types of arguments that SYMGET can receive.

Example 9.1: Using a Data Set Variable Name as the Argument to the SYMGET Function

Example 9.1 shows how the value of a data set variable can be used to specify the macro variable whose value SYMGET obtains. The open code %LET statements and the DATA step were presented earlier in this section.

Preceding the DATA step, %LET statements create six global macro variables, one for each of the six sections in the BOOK.YTDSALES data set. As the DATA step processes each observation in BOOK.YTDSALES, the SYMGET function extracts a value from one of the six macro variables based on the current observation’s value of the data set variable SECTION, and it stores the extracted value in DATA step variable SECTIONID. The value that the SYMGET function returns is a character value. The ATTRIB statement assigns a length of 9 bytes to SECTIONID, which overrides the default length of 200 bytes.

The data set variable COMPSECT that the data set creates stores the name of the macro variable that contains the specific section’s identification code. COMPSECT equals the first eight characters of the section name after blanks in those first eight characters have been removed.

%let certific=CRT283817;

%let networki=NET3UD697;

%let operatin=OPSI18375;

%let programm=PRG8361WQ;

%let software=SFT3521P8;

%let webdevel=WBD188377;

data temp;

  set books.ytdsales;

  attrib compsect length=$8 label='Section'

         sectionid length=$9 label='Section ID';

  *----Construct macro variable name by compressing

       section name and taking the first 8 characters.

       e.g. section=Programming, then COMPSECT=“Programm”;

  compsect=substr(compress(section),1,8);

  sectionid=symget(compsect);

run;

proc print data=temp;

  title “Defining the Section Identification Code”;

  var section compsect sectionid;

run;

Output 9.1 presents a partial listing of the PROC PRINT report produced by Example 9.1. The output shows the values assigned to SECTIONID by SYMGET.

Output 9.1 Partial output from Example 9.1

Output 9.1  Partial output from Example 9.1

Example 9.2: Retrieving Macro Variable Values and Creating Numeric Data Set Variables with SYMGET

Example 9.2 directly references two macro variables with the SYMGET function. The two macro variables are defined in open code preceding the DATA step in which they are referenced. On each iteration of the DATA step, SAS determines which macro variable value to retrieve based on the current observation’s value for data set variable SECTION. The DATA step selects specific

observations from the data set and then creates a new numeric variable whose value is the product of a variable in the data set and the value of a macro variable.

%let webfctr=1.20;

%let sftfctr=1.35;

data temp;

  set books.ytdsales(where=(

     section in ('Web Development', 'Software')));

  if section='Web Development' then

        costfctr=input(symget('webfctr'),best8.);

  else if section='Software' then

        costfctr=input(symget('sftfctr'),best8.);

  newprice=costfctr*cost;

run;

proc print data=temp;

  title “Prices based on COSTFCTR”;

  var booktitle section cost costfctr newprice;

  format newprice dollar8.2;

run;

Output 9.2 presents a partial listing of the PROC PRINT report produced by Example 9.2. The output shows that a value was assigned to COSTFCTR depending on the value of SECTION.

Output 9.2 Partial output from Example 9.2

Output 9.2  Partial output from Example 9.2

Example 9.3: Using the Resolution of a Character Expression As an Argument to SYMGET

The DATA step in Example 9.3 resolves SAS language character expressions to obtain the names and values of macro variables. The goal of the program is to obtain the manager’s initials for the quarter in which a book was sold. Preceding the DATA step, four %LET statements create four macro variables, one for the manager’s initials in each quarter.

As the DATA step processes each observation in BOOK.YTDSALES, the SYMGET function extracts a value from one of the four macro variables based on the current observation’s value of the data set variable DATESOLD. This value is assigned to data set variable MANAGERINITS. The quarter of the sale date is determined and the value of quarter (1, 2, 3, or 4) determines from which macro variable the SYMGET function retrieves a value.

The DATA step assigns a length of 3 bytes to MANAGERINITS, which overrides the default length of 200 bytes.

%let managerquarter1=LPL;

%let managerquarter2=EMB;

%let managerquarter3=EMB;

%let managerquarter4=ADL;

data managers;

  set books.ytdsales;

  length managerinits $ 3;

  managerinits=

       symget(cats('managerquarter',put(qtr(datesold),1.)));

run;

proc print data=managers;

  title “Sale Dates and Managers”;

  var datesold managerinits;

run;

Output 9.3 presents a partial listing of the PROC PRINT report produced by Example 9.3. The output shows the values assigned to MANAGERINITS by SYMGET.

Output 9.3 Partial output from Example 9.3

Output 9.3  Partial output from Example 9.3

Understanding the SYMPUT and SYMPUTX Call Routines

The SYMPUT and SYMPUTX SAS language call routines create macro variables during execution of a DATA step. If the macro variable already exists, these routines update the value of the macro variable.

CALL SYMPUTX. The syntax of the CALL SYMPUTX routine is:

CALL SYMPUTX(macro-variable,text<,symbol-table>)

CALL SYMPUT. The syntax of the SYMPUT routine is:

CALL SYMPUT(macro-variable,text)

The two functions differ in that CALL SYMPUTX trims leading and trailing blanks from the value assigned to the macro variable while CALL SYMPUT does not. Additionally, the CALL SYMPUTX allows you to specify the symbol table in which you want to store the macro variable.

In most situations, SAS recommends CALL SYMPUTX, and the examples in this section use only CALL SYMPUTX. CALL SYMPUTX is a newer function than CALL SYMPUT.

The first two arguments to CALL SYMPUTX and the two arguments to CALL SYMPUT can each be specified in one of three ways:

• as literal text. The following SAS language statement creates or updates the macro variable BOOKSECT with the value Software. Since CALL SYMPUTX is a SAS language routine, you must enclose literal text arguments in quotation marks.

call symputx('booksect','Software'),

• as the name of a data set character variable whose value is a SAS variable name. The current value of the data set variable NHIGH is assigned to the macro variable N30. The name of the macro variable, N30, is saved in DATA step character variable RESULTVAR.

resultvar='n30'; call symputx(resultvar,nhigh);

• as a character expression. The first argument to CALL SYMPUT below defines a macro variable name where the first part of the name is equal to the text AUTHORNAME. The second part of the macro variable name is equal to the automatic variable _N_. The second argument resolves to a text string. The literal text in the first part of the string and the current observation’s value for AUTHOR are concatenated. During the fifth iteration of the DATA step that contains this statement, CALL SYMPUT defines a macro variable named AUTHORNAME5.

call symputx(cats('authorname',put(_n_,4.)),            cat('Author Name: ',author));

The third argument to CALL SYMPUTX, which tells the macro processor the symbol table where to store the macro variable, is optional. This third argument can be specified as a character constant, data set variable, or expression. The first non-blank letter in this optional argument determines where the macro processor stores the macro variable. Valid values for this optional argument can be one of three values:

G, which specifies that the macro processor store the macro variable in the global symbol table even if the local symbol table exists.

L, which specifies that the macro processor store the macro variable in the most local symbol table. If a macro program is not executing when this option is specified, there will be no local symbol table. In such a situation, the most local symbol table is actually the global symbol table, which is where the macro processor will store the macro variable.

F, which specifies that if the macro variable exists in any symbol table, CALL SYMPUTX should update the macro variable’s value in the most local symbol table in which it exists. If it does not exist in any symbol table, CALL SYMPUTX stores the macro variable in the most local symbol table.

Each of these two call routines updates the value of an existing macro variable. A macro variable can have only one value. Even though your DATA step might cause the call routine to be executed with each pass of the DATA step, the macro variable that the routines reference can still have only one value. When the DATA step ends, the value of the macro variable being updated has the last value that was assigned by SYMPUT or SYMPUTX.

Example 9.4: Saving the Sum of a Variable in a Macro Variable by Executing CALL SYMPUTX Once at the End of a DATA Step

In Example 9.4, CALL SYMPUTX creates macro variable N30 whose value is the total number of books that sold for at least $30.00. The program then places this tally in the title of a PROC MEANS report.

The program directs that CALL SYMPUTX execute once when the DATA step reaches the end of the data set and that it store the formatted value of data set variable NHIGH in macro variable N30. The PUT function formats the value assigned to N30 with the COMMA format.

If the DATA step was written so that CALL SYMPUTX executed with each pass of the DATA step, the macro variable value would be updated with each observation. Since the goal is to obtain the total number of books that sold for more than $30.00, it is necessary to execute CALL SYMPUTX only once after the tally is complete. The second IF statement directs that the CALL SYMPUTX routine execute only when the DATA step reaches the end of data set BOOKS.YTDSALES.

data _null_;

  set books.ytdsales end=eof;

  if saleprice ge 30 then nhigh+1;

  if eof then call symputx('n30',put(nhigh,comma.));

run;

proc means data=books.ytdsales n mean min max sum maxdec=2;

  title “All Books Sold”;

  title2 “Number of Books Sold for More Than $30: &n30”;

  var saleprice;

run;

Output 9.4 presents the PROC MEANS report. The title includes the total number of books that sold for at least $30.00.

Output 9.4 Output from Example 9.4

Output 9.4  Output from Example 9.4

If you used CALL SYMPUT instead of CALL SYMPUTX, you might need to do additional processing to remove leading and trailing blanks. When you assign a numeric variable value to a macro variable with CALL SYMPUT, the numeric value is converted to character by default, and then this character value is stored in the macro variable. The default width of the character field passed to the macro variable is 12 characters and a numeric value is right aligned. Depending on the output destination of your report, you may have leading blanks before the value.

Leading blanks are removed when the output is sent to the HTML destination. If the output goes to the PDF or LISTING destinations, leading blanks are not removed.

Consider what happens when the CALL SYMPUT routine is used instead of CALL SYMPUTX, the PUT function is removed, and the destination is PDF.

  if eof then call symput('n30',nhigh);

The title now looks like the following, and eight leading blanks precede the four-digit numeric value.

Number of Books Sold for More Than $30:         1326

Execution of this version of the CALL SYMPUT function causes the following note to be written to the SAS log:

   NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column).

Example 9.5: Executing CALL SYMPUTX Multiple Times in a DATA Step

In Example 9.5, CALL SYMPUTX executes with each pass of the DATA step, which is once for each record in the data lines. The value of the macro variable at the end of the DATA step is the value from the last observation read from the raw data.

data newbooks;

  input booktitle $ 1-40;

  call symputx('lasttitle',booktitle);

datalines;

Hello Java Programming

My Encyclopedia of Networks

Strategic Computer Programming

Everyday Email Etiquette

run;

%put The value of macro variable LASTTITLE is &lasttitle..;

The %PUT statement writes the following to the SAS log.

The value of macro variable LASTTITLE is Everyday Email Etiquette.

Example 9.6: Creating Several Macro Variables with CALL SYMPUTX

CALL SYMPUTX creates multiple macro variables in this example. The DATA _NULL_ step creates two macro variables for each section in the output data set PROC FREQ created. PROC FREQ saves six observations in the SECTNAME output data set, one for each section in the BOOKS.YTDSALES data set. Therefore, the DATA step creates 12 macro variables. Six macro variables hold the names of the six sections. The other six macro variables hold the frequency counts for each of the sections. A %PUT _USER_ following the DATA step lists the 12 macro variables created in the DATA step.

proc freq data=books.ytdsales noprint;

   tables section / out=sectname;

run;

data _null_;

  set sectname;

  call symputx(cats('name',put(_n_,1.)),section);

  call symputx(cats('n',put(_n_,1.)),count);

run;

%put _user_;

The following %PUT _USER_ output displays the values of the macro variables defined in the DATA step.

GLOBAL NAME1 Certification and Training

GLOBAL N1 524

GLOBAL NAME2 Networking

GLOBAL N2 479

GLOBAL NAME3 Operating Systems

GLOBAL N3 578

GLOBAL NAME4 Programming

GLOBAL N4 337

GLOBAL NAME5 Software

GLOBAL N5 857

GLOBAL NAME6 Web Development

GLOBAL N6 571

Example 9.7: Creating a Macro Variable with CALL SYMPUTX and Specifying Its Symbol Table

Example 9.7 computes statistics on a subset of a data set and assigns the values of the statistics to global macro variables. The goal is to make these macro variables global so that they are available for subsequent processing.

Macro program STATSECTION computes with PROC MEANS the mean, minimum, and maximum sale price for a specific section in BOOKS.YTDSALES; the program saves the statistics in output data set SECTIONRESULTS. The parameter SECTION passes to STATSECTION the name of the section for which to compute the statistics.

The PROC MEANS step does not print a report, but it does save the three statistics in an output data set. A DATA step processes the output data set. It uses CALL SYMPUTX to create three macro variables to hold the three statistics and to assign values to the macro variables. Additionally, CALL SYMPUTX specifies that the macro variables be stored in the global symbol table.

The three global macro variables created by this program are AVERAGE, MIN, and MAX. Three CALL SYMPUTX statements store the formatted values of the statistics in these macro variables.

If you did not specify that the macro processor store the macro variables in the global symbol table, the macro processor stores them in the local symbol table defined by macro program STATSECTION. Once STATSECTION completed processing, its local symbol table is deleted, and the values of the three macro variables are lost.

Macro program STATSECTION includes a %PUT _LOCAL_ statement to show that the only macro variable stored in the STATSECTION local macro symbol table is SECTION. (You could also use the %SYMGLOBL and %SYMLOCAL macro variable attribute functions described in Chapter 6 to determine whether a macro variable was stored globally or locally.)

Three TITLE statements follow the call to STATSECTION. These TITLE statements include references to the three macro variables created in STATSECTION.

%macro statsection(section);

  proc means data=books.ytdsales noprint;

    where section=“&section”;

    var saleprice;

    output out=sectionresults mean=avgsaleprice

             min=minsaleprice max=maxsaleprice;

  run;

  data _null_;

    set sectionresults;

    call symputx('average',put(avgsaleprice,dollar8.2),'G'),

    call symputx('min',put(minsaleprice,dollar8.2),'G'),

    call symputx('max',put(maxsaleprice,dollar8.2),'G'),

  run;

  %* Submit this statement to see the variables stored in the

     STATSECTION local symbol table;

  %put _local_;

%mend;

%statsection(Software)

title “Section Results for Average Sale Price: &average”;

title2 “Minimum Sale Price: &min”;

title3 “Maximum Sale Price: &max”;

Execution of the %PUT _LOCAL_ statement writes the following to the SAS log. The text “STATSECTION” refers to the name of the local symbol table.

STATSECTION SECTION Software

After executing %STATSECTION and the subsequent TITLE statements, the titles become:

Section Results for Average Sale Price: $34.28

Minimum Sale Price: $28.04

Maximum Sale Price: $39.06

If you dropped the third argument in the three CALL SYMPUTX calls, the macro processor stores the three macro variables in the STATSECTION local symbol table. Then when STATSECTION ends, the macro processor deletes the STATSECTION local symbol table; the values of the three macro variables are not available for insertion into the titles.

The three DATA step statements would be rewritten as follows.

call symputx('average',put(avgsaleprice,dollar8.2));

call symputx('min',put(minsaleprice,dollar8.2));

call symputx('max',put(maxsaleprice,dollar8.2));

The %PUT _LOCAL_ statement would now produce the following output in the SAS log.

  STATSECTION MIN $28.04

  STATSECTION MAX $39.06

  STATSECTION SECTION Software

  STATSECTION AVERAGE $34.28

The references to the three macro variables in the TITLE statements cannot be resolved because the macro variables do not exist in the global symbol table. With the three macro variables stored in the local macro symbol table, the three titles become:

Section Results for Average Sale Price: &average

Minimum Sale Price: &min

Maximum Sale Price: &max

Note that if you want to try out the code that does not specify that the macro processor save the macro variables in the global symbol table and you want to see the unresolved macro variable results in the titles, make sure you delete the three macro variables from the global symbol table. You can delete the three macro variables with the %SYMDEL statement.

%symdel average min max;

Understanding the CALL EXECUTE Routine

The CALL EXECUTE SAS language routine in a DATA step takes as its argument a character expression or constant text that SAS resolves to a macro program invocation or SAS statements. With CALL EXECUTE, you can conditionally call a macro program using SAS language logic statements such as IF-THEN-ELSE. Additionally, you can assign a DATA step variable’s value as a parameter to the macro program that CALL EXECUTE references.

The argument that you supply to CALL EXECUTE does not only have to resolve to a macro program reference. As mentioned above, the argument to CALL EXECUTE can be SAS language statements. For detailed information on how to use CALL EXECUTE in this context, refer to SAS documentation.

When the argument to CALL EXECUTE is a macro program reference, that macro program executes immediately during execution of the DATA step. However, if that macro program generates a DATA step or PROC step, those steps execute after the DATA step finishes.

The syntax of the CALL EXECUTE routine is

call execute('argument')

The three types of arguments that can be supplied to the routine are:

• a text string enclosed in quotation marks. Single quotation marks and double quotation marks are handled differently. Single quotation marks cause the argument to be resolved when the DATA step executes. Double quotation marks cause the argument to be resolved by the macro processor during construction of the DATA step, before compilation and execution of the DATA step.

• the name of a data set character variable. This variable’s value can be a text expression or a SAS language statement. Do not enclose the variable name in quotation marks.

• a text expression that the DATA step can resolve to a SAS language statement or to a macro variable, macro language statement, or macro program reference.

Example 9.8: Illustrating the Timing of CALL EXECUTE When It Invokes a Macro Program That Submits Macro Statements

Example 9.8 is a simple example that demonstrates how a macro program invoked by CALL EXECUTE executes immediately within the DATA step. The macro program LISTAUTOMATIC issues a %PUT statement that lists the automatic variables. The DATA step that follows contains a CALL EXECUTE statement that explicitly invokes LISTAUTOMATIC.

%macro listautomatic;

  %put **** Start list of automatic macro variables;

  %put _automatic_;

  %put **** End list of automatic macro variables;

%mend listautomatic;

data _null_;

  call execute('%listautomatic'),

run;

The SAS log for this program shows that the macro program executes during execution of the DATA step. The results of the %PUT _AUTOMATIC_ statement appear before the notes that indicate the DATA step has ended. SAS informs you when your CALL EXECUTE does not generate any SAS language statements, as shown by the last note.

48   %macro listautomatic;

49     %put **** Start list of automatic macro variables;

50     %put _automatic_;

51     %put **** End list of automatic macro variables;

52   %mend listautomatic;

53

54   data _null_;

55     call execute('%listautomatic'),

56   run;

**** Start list of automatic macro variables

AUTOMATIC AFDSID 0

AUTOMATIC AFDSNAME

AUTOMATIC AFLIB

AUTOMATIC AFSTR1

AUTOMATIC AFSTR2

AUTOMATIC FSPBDV

AUTOMATIC SYSBUFFR

.

.

.

AUTOMATIC SYSTIME 08:20

AUTOMATIC SYSUSERID My Userid

AUTOMATIC SYSVER 9.4

.

.

.

**** End list of automatic macro variables

NOTE: DATA statement used (Total process time):

      real time           0.00 seconds

      cpu time            0.00 seconds

 

NOTE: CALL EXECUTE routine executed successfully, but no SAS  statements were generated.

Example 9.9:  Illustrating the Timing of CALL EXECUTE When It Invokes a Macro Program That Submits Macro Statements and a PROC Step

Example 9.9 demonstrates that macro statements execute during execution of a DATA step and that SAS statements generated by the macro program execute after the DATA step finishes. It defines and invokes macro program LISTLIBRARY that submits two %PUT statements and a PROC DATASETS step. Two SAS language PUT statements illustrate the timing of SAS language statements within the DATA step that submits CALL EXECUTE.

The macro program LISTLIBRARY issues a PROC DATASETS for the BOOKS library. Within LISTLIBRARY, a %PUT precedes the PROC step code, and a second %PUT statement follows the PROC step code. Within the DATA step, one PUT statement precedes and a second PUT statement follows CALL EXECUTE.

%macro listlibrary;

    %put

**** This macro statement in LISTLIBRARY precedes the PROC step code.;

  proc datasets library=books;

  run;

  quit;

  %put

**** This macro statement in LISTLIBRARY follows the PROC step code.;

%mend listlibrary;

data _null_;

  put “This SAS language statement precedes the macro program call.”;

  call execute('%listlibrary'),

  put “This SAS language statement follows the macro program call.”;

run;

The SAS log for this program shows that the %PUT statements execute during execution of the DATA step as do the SAS language PUT statements. The text written by the %PUT statements appears in the SAS log during execution of the DATA step. The PROC DATASETS output, however, does not appear until after the DATA step concludes.

During execution of the DATA step, the macro processor directs immediate execution of the two %PUT statements while it places the PROC step on the input stack for execution after the DATA step concludes.

140  %macro listlibrary;

141    %put **** This macro statement in LISTLIBRARY precedes the PROC step;

142    proc datasets library=books;

143    run;

144    quit;

145    %put **** This macro statement in LISTLIBRARY follows the PROC step;

146  %mend listlibrary;

147

148  data _null_;

149    put “This SAS language statement precedes the macro program call.”;

150    call execute('%listlibrary'),

151    put “This SAS language statement follows the macro program call.”;

152  run;

 

This SAS language statement precedes the macro program call.

**** This macro statement in LISTLIBRARY precedes the PROC step

**** This macro statement in LISTLIBRARY follows the PROC step

This SAS language statement follows the macro program call.

NOTE: DATA statement used (Total process time):

      real time           0.00 seconds

      cpu time            0.00 seconds

NOTE: CALL EXECUTE generated line.

1   + proc datasets library=books;

                            Directory

           Libref         BOOKS

           Engine         V9

           Physical Name  f:ooks 

           File Name      f:ooks

                      Member      File

         #  Name      Type        Size  Last Modified

         1  YTDSALES  DATA     771072  02Feb15:16:21:13

1   +                           run;

1   +                                       quit;

NOTE: PROCEDURE DATASETS used (Total process time):

      real time           0.00 seconds

      cpu time            0.00 seconds

Example 9.10: Using CALL EXECUTE to Conditionally Call a Macro Program

Example 9.10 uses CALL EXECUTE to conditionally execute the macro program REP16K. First, PROC MEANS computes the sales for each section in BOOKS.YTDSALES and stores the results in an output data set. A DATA step processes the output data set and examines the total sales per section. When the sales exceed $16,000, the CALL EXECUTE statement in the DATA step calls macro program REP16K.

The argument to CALL EXECUTE is the macro program name, REP16K. This macro program has one parameter, SECTION. The argument to CALL EXECUTE is a text expression that resolves to the call to REP16K with the parameter specified as the current value of SECTION. The CATS function concatenates the parts of the macro program call.

The SAS language statements in the macro program execute when the DATA step finishes. In this example, the CALL EXECUTE routine executes as many times as there are observations that satisfy the IF statement condition. Each time CALL EXECUTE executes, it calls the macro program REP16K for the section value of the current observation. Therefore, when the DATA step finishes, there can be several PROC REPORT steps on the input stack ready to process.

In this example, total sales exceed $16,000 in two sections, “Certification and Training” and “Software”. Thus, two PROC REPORT steps execute after the DATA step.

%macro rep16k(section);

  proc report data=books.ytdsales center nowd;

    where section=“&section”;

    title “Sales > $16,000 Summary for &section”;

    column  publisher n saleprice;

    define  publisher / group;

    define  n / “Number of Books Sold” ;

    define  saleprice / sum format=dollar10.2 “Sale Price” ;

    rbreak after / summarize;

  run;

%mend rep16k;

options mprint;

proc means data=books.ytdsales nway noprint;

  class section;

  var saleprice;

 

  output out=sectsale sum=totlsale;

run;

data _null_;

  set sectsale;

  if totlsale > 160000 then

    call execute(cats('%rep60k(',section,')'));

run;

The SAS log for this program shows that two PROC REPORT steps execute after completion of the DATA step. The option MPRINT is in effect and shows the code for the two PROC REPORT steps. Note that the processing of CALL EXECUTE also lists the code for the PROC REPORT steps.

222  %macro rep16k(section);

223    proc report data=books.ytdsales nowd;

224      where section=“&section”;

225      title “Sales > $16,000 Summary for &section”;

226      column  publisher n saleprice;

227      define  publisher / group;

228      define  n / “Number of Books Sold” ;

229      define  saleprice / sum format=dollar10.2 “Sale Price” ;

230      rbreak after / summarize;

231      compute after;

232        publisher=“**Total”;

233      endcomp;

234    run;

235  %mend rep16k;

236

237  options mprint;

238

239  proc means data=books.ytdsales nway noprint;

240    class section;

241    var saleprice;

242    output out=sectsale sum=totlsale;

243  run;

NOTE: There were 3346 observations read from the data set

      BOOKS.YTDSALES.

NOTE: The data set WORK.SECTSALE has 6 observations and 4 variables.

NOTE: PROCEDURE MEANS used (Total process time):

      real time           0.04 seconds

      cpu time            0.00 seconds

244

245  data _null_;

246    set sectsale;

247

248    if totlsale > 16000 then

249      call execute(cats('%rep16k(',section,')'));

250  run;

MPRINT(REP16K):   proc report data=books.ytdsales nowd;

MPRINT(REP16K):   where section=“Certification and Training”;

MPRINT(REP16K):   title “Sales >$16,000 Summary for Certification and Training”;

MPRINT(REP16K):   column publisher n saleprice;

MPRINT(REP16K):   define publisher / group;

MPRINT(REP16K):   define n / “Number of Books Sold” ;

MPRINT(REP16K):   define saleprice / sum format=dollar10.2 “Sale Price” ;

MPRINT(REP16K):   rbreak after / summarize;

MPRINT(REP16K):   compute after;

MPRINT(REP16K):   publisher=“**Total”;

MPRINT(REP16K):   endcomp;

MPRINT(REP16K):   run;

MPRINT(REP16K):   proc report data=books.ytdsales nowd;

MPRINT(REP16K):   where section=“Software”;

MPRINT(REP16K):   title “Sales >$16,000 Summary for Software”;

MPRINT(REP16K):   column publisher n saleprice;

MPRINT(REP16K):   define publisher / group;

MPRINT(REP16K):   define n / “Number of Books Sold” ;

MPRINT(REP16K):   define saleprice / sum format=dollar10.2 “Sale Price” ;

MPRINT(REP16K):   rbreak after / summarize;

MPRINT(REP16K):   compute after;

MPRINT(REP16K):   publisher=“**Total”;

MPRINT(REP16K):   endcomp;

MPRINT(REP16K):   run;

NOTE: There were 6 observations read from the data set WORK.SECTSALE.

NOTE: DATA statement used (Total process time):

      real time           0.02 seconds

      cpu time            0.01 seconds

NOTE: CALL EXECUTE generated line.

1   + proc report data=books.ytdsales nowd;     where section=“Certification and Training”;

 title “Sales > $16,000 Summary for Certification and Training”;     column  publisher n

saleprice;     define  publisher / group;     define  n / “Number of Books

2   + Sold” ;     define  saleprice / sum format=dollar10.2 “Sale Price” ;     rbreak after /

summarize;     compute after;       publisher=“**Total”;     endcomp;   run;

NOTE: There were 524 observations read from the data set

      BOOKS.YTDSALES.

      WHERE section='Certification and Training';

NOTE: PROCEDURE REPORT used (Total process time):

      real time           0.03 seconds

      cpu time            0.01 seconds

3   + proc report data=books.ytdsales nowd;     where section=“Software”;     title “Sales >

$16,000 Summary for Software”;     column  publisher n saleprice;     define  publisher /

group;     define  n / “Number of Books Sold” ;     define  saleprice / sum

4   + format=dollar10.2 “Sale Price” ;     rbreak after / summarize;     compute after;

publisher=“**Total”;     endcomp;   run;

NOTE: There were 857 observations read from the data set

      BOOKS.YTDSALES.

      WHERE section='Software';

NOTE: PROCEDURE REPORT used (Total process time):

      real time           0.04 seconds

      cpu time            0.01 seconds

Example 9.11: Using CALL EXECUTE to Call a Specific Macro Program

Example 9.11 shows how you can conditionally call different macro programs during the execution of a DATA step. The PROC steps constructed by the macro program execute after the DATA step ends.

Example 9.11 defines two macro programs: LOWREPORT and HIGHREPORT. Each macro program generates a different PROC REPORT step.

As in Example 9.10, PROC MEANS computes total sales by section and saves the results in an output data set. A DATA step examines the results and, depending on the value of the total sales, it determines whether one of the two macro programs should be executed. If sales exceed $20,000, then CALL EXECUTE specifies a call to macro program HIGHREPORT. If sales are less than $12,000, then CALL EXECUTE specifies a call to macro program LOWREPORT. Neither macro program is called if sales are between $12,000 and $20,000.

The argument to each of the two CALL EXECUTE references is a text expression that resolves either to a call to HIGHREPORT or to a call to LOWREPORT. Both macro programs have the same parameter, SECTION. The current observation’s value of SECTION is specified as part of the text expression that resolves to the macro program call. The CATS function concatenates the parts of the macro program call.

In this example, section “Software” exceeds total sales of $20,000. The DATA step calls macro program HIGHREPORT once.

Two sections, “Networking” and “Programming,” have total sales less than $12,000. The DATA step calls macro program LOWREPORT twice, once for each of these sections.

%macro highreport(section);

   proc report data=books.ytdsales nowd;

     where section=“&section”;

     title “Sales > $20,000 Report for Section &section”;

     column  publisher n saleprice;

     define  publisher / group;

     define  n / “Number of Books Sold” ;

     define  saleprice / sum format=dollar10.2 “Sale Price” ;

     rbreak after / summarize;

     compute after;

       publisher=“**Total”;

     endcomp;

  run;

%mend highreport;

%macro lowreport(section);

   proc report data=books.ytdsales nowd;

     where section=“&section”;

     title “Sales < $12,000 Report for Section &section”;

     column datesold n saleprice;

     define datesold / group format=monname15. “Month Sold”

                       style(column)=[just=left];

     define n / “Number of Books Sold”;

     define saleprice / sum format=dollar10.2 “Sales Total”;

     rbreak after / summarize;

   run;

%mend lowreport;

proc means data=books.ytdsales nway noprint;

  class section;

  var saleprice;

  output out=sectsale sum=totlsect;

run;

data _null_;

  set sectsale;

  if totlsect < 12000 then

    call execute(cats('%lowreport(',section,')'));

  else if totlsect > 20000 then

    call execute(cats('%highreport(',section,')'));

run;

The SAS log for this program shows the three calls to the two macro programs. Compared to Example 9.10, MPRINT is not in effect when Example 9.11 executes. The results of the CALL EXECUTE call, however, are displayed.

951  %macro highreport(section);

952     proc report data=books.ytdsales nowd;

953       where section=“&section”;

954       title “Sales > $20,000 Report for Section &section”;

955       column  publisher n saleprice;

956       define  publisher / group;

957       define  n / “Number of Books Sold” ;

958       define  saleprice / sum format=dollar10.2 “Sale Price” ;

959       rbreak after / summarize;

960       compute after;

961         publisher=“**Total”;

962       endcomp;

963    run;

964  %mend highreport;

965

966  %macro lowreport(section);

967     proc report data=books.ytdsales nowd;

968       where section=“&section”;

969       title “Sales < $12,000 Report for Section &section”;

970       column datesold n saleprice;

971       define datesold / group format=monname15. “Month Sold”

972                         style(column)=[just=left];

973       define n / “Number of Books Sold”;

974       define saleprice / sum format=dollar10.2 “Sales Total”;

975       rbreak after / summarize;

976     run;

977  %mend lowreport;

978

979  proc means data=books.ytdsales nway noprint;

980    class section;

981    var saleprice;

982    output out=sectsale sum=totlsect;

983  run;

NOTE: There were 3346 observations read from the data set

      BOOKS.YTDSALES.

NOTE: The data set WORK.SECTSALE has 6 observations and 4 variables.

NOTE: PROCEDURE MEANS used (Total process time):

      real time           0.04 seconds

      cpu time            0.01 seconds

984

985  data _null_;

986    set sectsale;

987    if totlsect < 12000 then

988      call execute(cats('%lowreport(',section,')'));

989

990    else if totlsect > 20000 then

991      call execute(cats('%highreport(',section,')'));

992  run;

NOTE: There were 6 observations read from the data set WORK.SECTSALE.

NOTE: DATA statement used (Total process time):

      real time           0.00 seconds

      cpu time            0.01 seconds

NOTE: CALL EXECUTE generated line.

1   + proc report data=books.ytdsales nowd;      where section=“Networking”;      title “Sales

< $12,000 Report for Section Networking”;      column datesold n saleprice;      define

datesold / group format=monname15. “Month Sold”                        style

2   +(column)=[just=left];      define n / “Number of Books Sold”;      define saleprice / sum

format=dollar10.2 “Sales Total”;      rbreak after / summarize;    run;

NOTE: There were 479 observations read from the data set

      BOOKS.YTDSALES.

      WHERE section='Networking';

NOTE: PROCEDURE REPORT used (Total process time):

      real time           0.03 seconds

      cpu time            0.01 seconds

3   + proc report data=books.ytdsales nowd;      where section=“Programming”;      title

“Sales < $12,000 Report for Section Programming”;      column datesold n saleprice;

define datesold / group format=monname15. “Month Sold”

4   + style(column)=[just=left];      define n / “Number of Books Sold”;      define saleprice

/ sum format=dollar10.2 “Sales Total”;      rbreak after / summarize;    run;

NOTE: There were 337 observations read from the data set

      BOOKS.YTDSALES.

      WHERE section='Programming';

NOTE: PROCEDURE REPORT used (Total process time):

      real time           0.03 seconds

      cpu time            0.00 seconds

5   + proc report data=books.ytdsales nowd;      where section=“Software”;      title “Sales >

$20,000 Report for Section Software”;      column  publisher n saleprice;      define

publisher / group;      define  n / “Number of Books Sold” ;      define

6   + saleprice / sum format=dollar10.2 “Sale Price”;      rbreak after / summarize;

compute after;        publisher=“**Total”;      endcomp;   run;

NOTE: There were 857 observations read from the data set

      BOOKS.YTDSALES.

      WHERE section='Software';

NOTE: PROCEDURE REPORT used (Total process time):

      real time           0.03 seconds

      cpu time            0.00 seconds

Understanding the RESOLVE Function

The RESOLVE SAS language function can resolve a macro variable reference or macro program call during execution of a DATA step. The result returned by RESOLVE is a character value whose length equals that of the data set character variable to which the result is being assigned. It takes as its argument a text expression, a data set character variable, or a character expression that produces a text expression that can be resolved by the macro processor.

The RESOLVE function acts during execution of a DATA step. Therefore, a RESOLVE function could be coded so that it executes with each pass of a DATA step, and at each execution it could return a different value.

The RESOLVE function is similar to the SYMGET function in that both functions can resolve macro variable references during execution of a DATA step. However, the SYMGET function is more limited in its functionality and in the arguments it can accept. The RESOLVE function can accept a variety of different types of arguments, including macro variables and macro program calls, while SYMGET’s sole function is to resolve a macro variable reference.

The SYMGET function can resolve macro variables only if they exist before execution of the DATA step in which the function is included. An exception to this is if a statement containing CALL SYMPUT or CALL SYMPUTX that defines the macro variable executes before the SYMGET function. As stated above, the RESOLVE function acts during execution, and a macro variable defined in a DATA step with CALL SYMPUT or CALL SYMPUTX can be retrieved in the same DATA step with the RESOLVE function.

The syntax of the RESOLVE function is

resolve('argument')

The three types of arguments that RESOLVE accepts are:

• a text expression that is enclosed in single quotation marks. This text expression can be a macro variable reference, an open code macro language statement, or a macro program call. If you enclose the text expression in double quotation marks, the macro processor attempts to resolve it before the DATA step is compiled, while the SAS program is being constructed. Enclosing the argument in single quotation marks delays resolution until the DATA step executes.

dsvar=resolve('&macvar'),

• the name of a data set character variable. The value of this variable is a text expression representing a macro variable reference, an open code macro language statement, or a macro program call.

%let label1=All the Books Sold;

data temp;

  length textlabel $ 40;

  macexp='&label1';

  textlabel=resolve(macexp);

run;

• a character expression that can be resolved to a text expression. The text expression represents a macro variable reference, an open code macro language statement, or a macro program call.

%let quartersale1=Holiday Clearance;

%let quartersale2=2 for the Price of 1;

%let quartersale3=Back to School;

%let quartersale4=New Releases;

data temp;

  set books.ytdsales;

  length quartersalename $ 30;

 

  quarter=qtr(datesold);

  quartersalename=resolve(

       cats('&quartersale',put(quarter,1.)) );

run;

By default, the length of the text value returned by RESOLVE is 200 bytes. If you want the character variable that holds the result to have a different length, you must explicitly define the length for the variable. This can be done with the LENGTH statement or with the ATTRIB statement.

Example 9.12: Obtaining Macro Variable Values with RESOLVE by Resolving Character Expressions

The code in Example 9.12 was presented above in the discussion on the types of arguments that RESOLVE can accept. The goal of Example 9.12 is to create a character variable that contains the name of the sale in the quarter in which an item was sold. Sale names are stored in macro variables. The RESOLVE function in the DATA step looks up the correct sale name based on the quarter the item was sold. The argument to the RESOLVE function is a character expression that resolves to a macro variable name.

Example 9.12 defines four macro variables, QUARTERSALE1, QUARTERSALE2, QUARTERSALE3, and QUARTERSALE4, which contain the name of each quarter’s sale. The DATA step processes data set BOOKS.YTDSALES and determines the quarter in which each item sold. A macro variable name is constructed by concatenating the text part of the macro variable name, QUARTERSALE, to the quarter number. This expression is the argument to RESOLVE. RESOLVE returns the value of the specific macro variable and assigns this value to data set character variable QUARTERSALENAME.

Note that the text &QUARTERSALE is enclosed in single quotation marks. The single quotation marks prevent the macro processor from attempting to resolve a macro variable with that name during compilation of the DATA step.

Output 9.5 shows the results of the PROC FREQ crosstabulation of QUARTER and QUARTERSALENAME.

%let quartersale1=Holiday Clearance;

%let quartersale2=2 for the Price of 1;

%let quartersale3=Back to School;

%let quartersale4=New Releases;

data temp;

  set books.ytdsales;

  length quartersalename $ 30;

  quarter=qtr(datesold);

  quartersalename=resolve(

       cats('&quartersale',put(quarter,1.)) );

run;

proc freq data=temp;

  title 'Quarter by Quarter Sale Name';

  tables quarter*quartersalename / list nocum nopct;

run;

Output 9.5 presents the PROC FREQ results produced by Example 9.12.

Output 9.5 Output from Example 9.12

Output 9.5  Output from Example 9.12

Example 9.13: Using RESOLVE to Call a Macro Program within a DATA Step That Assigns Text to a Data Set Variable

This example shows how you can call a macro program from within a DATA step with the RESOLVE function. The macro program executes with each pass of the DATA step and it returns text to the DATA step.

As in Example 9.12, Example 9.13 looks up a sale name based on the quarter. In this example, PROC MEANS computes total sales by quarter for variable SALEPRICE and saves the results in an output data set. A DATA step processes the output data set created by PROC MEANS. The RESOLVE function executes the same macro program with each pass of the DATA step. The value of quarter is passed as a parameter to the macro program.

The definition for macro program GETSALENAME precedes the PROC MEANS step. When called by the RESOLVE function, macro program GETSALENAME simply looks up a text value based on the value of parameter QUARTER and returns this text to the DATA step. The assignment statement in the DATA step assigns this text value to data set variable QUARTERSALENAME.

As in Example 9.12, the argument to the RESOLVE function in Example 9.13 is constructed during execution of the DATA step, and the argument is enclosed in single quotation marks, which prevent the macro processor from attempting to resolve the call to the macro program during compilation of the DATA step.

%macro getsalename(quarter);

  %if &quarter=1 %then %do;

    Holiday Clearance

  %end;

  %else %if &quarter=2 %then %do;

    2 for the Price of 1

  %end;

  %else %if &quarter=3 %then %do;

    Back to School

  %end;

  %else %if &quarter=4 %then %do;

    New Releases

  %end;

%mend getsalename;

proc means data=books.ytdsales noprint nway;

  class datesold;

  var saleprice;

  output out=quarterly sum=;

  format datesold qtr.;

run;

data quarterly;

  set quarterly(keep=datesold saleprice);

  length quartersalename $ 30;

  quartersalename=resolve( cats('%getsalename(',put(datesold,qtr.),')') );

run;

proc print data=quarterly label;

  title 'Quarter Sales with Quarter Sale Name';

  label datesold='Quarter'

        saleprice='Total Sales'

        quartersalename='Sale Name';

run;

Output 9.6 presents the PROC PRINT report produced by Example 9.13.

Output 9.6 Output from Example 9.13

Output 9.6  Output from Example 9.13

Using Macro Facility Features in PROC SQL

Elements of PROC SQL can interface with the macro facility. During execution of a PROC SQL step, you can create and update macro variables. Additionally, with each execution of PROC SQL, the procedure creates and maintains macro variables that hold information about the processing of the PROC SQL step. This section describes only the macro facility interface features of PROC SQL. For complete information on PROC SQL, refer to PROC SQL documentation.

Creating and Updating Macro Variables with PROC SQL

The INTO clause on the SELECT statement can create and update macro variables. Calculations that are done with the SELECT statement, as well as entire data columns, can be saved in the macro variables that you name with the INTO clause.

The INTO clause is analogous to the CALL SYMPUT and CALL SYMPUTX routines in the DATA step. Like these routines, the INTO clause creates and updates macro variables during execution of a step. In the case of the INTO clause, the step is a PROC SQL statement.

The INTO clause provides a link to the macro variable symbol table during execution of PROC SQL. Values that are assigned to the macro variables are considered to be text.

In general, SAS adds the macro variables that you create with PROC SQL to the most local macro symbol table available when PROC SQL executes. If PROC SQL is not submitted from within a macro program, the macro processor stores the macro variables in the global macro symbol table.

The basic syntax of the INTO clause on the PROC SQL SELECT statement follows:

SELECT col1,col2,...

       INTO :macro-variable-specification

            <, . . .macro-variable-specification>

       FROM table-expression

       WHERE where-expression

       other clauses;

Note the punctuation on the INTO clause: the macro variable names are preceded with colons (:), not ampersands (&). Macro variables are named explicitly on the INTO clause. Numbered lists of macro variables can also be specified on the INTO clause. The macro variable specification can be written as follows.

• If you want to store the first value returned into a single macro variable, use this syntax. Leading and trailing blanks are preserved unless the TRIMMED option is specified.

:macro-variable <TRIMMED>

• If you want to store a series of values that are returned in a single macro variable, use this syntax. Unless the NOTRIM option is included, SAS removes leading and trailing blanks from the values saved in the macro variable. The SEPARATED BY option is required, and it specifies the character(s) that indicate row separation in the value of macro-variable.

:macro-variable <SEPARATED BY 'character(s)'<NOTRIM>>

• If you want to store the values that the SELECT statement returns in a series of macro variables, use this syntax. The value N does not have to be exactly equal to the number of values returned. If N is greater than the number of values returned, SAS creates the number of macro variables equal to the number returned. If N is less than the number of values returned, SAS creates only N macro variables. Unless the NOTRIM option is included, SAS removes leading and trailing blanks from the values saved in the macro variables.

:macro-variable-1 - macro-variable-n <NOTRIM>

• Another way of specifying a series of macro variables follows. The upper limit of the series is not specified. In this situation, SAS creates the number of macro variables equal to the number of values returned. Unless the NOTRIM option is included, SAS removes leading and trailing blanks from the values saved in the macro variables.

:macro-variable-1 - <NOTRIM>

The INTO clause cannot be used during creation of a table or view. It can be used only on outer queries of the SELECT statement.

Example 9.14:  Using the INTO Clause in PROC SQL to Save Summarizations in Macro Variables

Example 9.14 presents a simple application of the INTO clause. The PROC SQL SELECT statement computes the total sales and the total number of books sold for a specific publisher identified by macro variable FINDPUBLISHER. It stores the computations in two macro variables, TOTSALES and NSOLD. A %PUT statement following the step writes the values of these two global macro variables to the SAS log.

%let findpublisher=Technology Smith;

proc sql noprint;

  select sum(saleprice) format=dollar10.2,

         count(saleprice)

    into :totsales, :nsold

    from books.ytdsales

    where publisher=“&findpublisher”;

quit;

%put &findpublisher Total Sales=&totsales;

%put &findpublisher Total Number Sold=&nsold;

The SAS log for the preceding program follows.

27   %let findpublisher=Technology Smith;

28   proc sql noprint;

29     select sum(saleprice) format=dollar10.2,

30            count(saleprice)

31       into :totsales, :nsold

32       from books.ytdsales

33       where publisher=“&findpublisher”;

34   quit;

NOTE: PROCEDURE SQL used (Total process time):

      real time           0.00 seconds

      cpu time            0.00 seconds

35   %put &findpublisher Total Sales=&totsales;

36   %put &findpublisher Total Number Sold=&nsold;

Technology Smith Total Sales= $5,503.41

Technology Smith Total Number Sold=     238

Notice the leading blanks before the resolved macro variable values on the results of the two %PUT statements. If you add the TRIMMED option to each macro variable reference on the INTO clause, SAS removes the leading blanks.

into :totsales trimmed, :nsold trimmed

When the INTO clause includes the two TRIMMED options, the results of the %PUT statements are as follows.

Technology Smith Total Sales=$5,503.41

Technology Smith Total Number Sold=238

Example 9.15:  Demonstrating the Default Action of the INTO Clause in Saving the First Row of a Table

The default action of the PROC SQL INTO clause stores the first row of a table in the macro variables named on the INTO clause. This example demonstrates that action.

Example 9.15 sorts the BOOKS.YTDSALES data set by DATESOLD and saves the sorted observations in data set DATESORTED. The PROC SQL step creates three macro variables FIRSTDATE, FIRSTTITLE, and FIRSTPRICE, and it sets their values to the values of data set variables DATESOLD, BOOKTITLE, and SALEPRICE for the first observation in DATESORTED. Three %PUT statements following the step write the values of these three global macro variables to the SAS log. A PROC PRINT of the first five observations of DATESORTED shows that the values assigned to the macro variables were from the first observation in DATESORTED.

proc sort data=books.ytdsales out=datesorted;

  by datesold;

run;

proc sql noprint;

  select datesold,booktitle,saleprice

    into :firstdate,:firsttitle,:firstprice

    from datesorted;

quit;

%put One of the first books sold was on &firstdate;

%put The title of this book is &firsttitle;

%put The sale price was &firstprice;

proc print data=datesorted(obs=5);

  title

   'First Five Observations of Sorted by Date BOOKS.YTDSALES';

run;

The SAS log displays the values of the three macro variables.

6611  proc sql noprint;

6612    select datesold,booktitle,saleprice

6613      into :firstdate,:firsttitle,:firstprice trimmed

6614      from datesorted;

6615  quit;

NOTE: PROCEDURE SQL used (Total process time):

      real time           0.00 seconds

      cpu time            0.00 seconds

6616  %put One of the first books sold was on &firstdate;

One of the first books sold was on 01/01/2014

6617  %put The title of this book is &firsttitle;

The title of this book is Web Development Title 9

6618  %put The sale price was &firstprice;

The sale price was $23.68

6619  proc print data=datesorted(obs=5);

6620    title 'First Five Observations of Sorted by Date BOOKS.YTDSALES';

6621  run;

NOTE: There were 5 observations read from the data set WORK.DATESORTED.

NOTE: PROCEDURE PRINT used (Total process time):

      real time           0.00 seconds

      cpu time            0.00 seconds

Output 9.7 shows the PROC PRINT report that verifies the values of the macro variables created by the PROC SQL step.

Output 9.7 Output from Example 9.15

Output 9.7  Output from Example 9.15

Example 9.16: Using the INTO Clause in PROC SQL to Create a Macro Variable for Each Row in a Table

Numbered lists on the INTO clause can store rows of a table in macro variables. The PROC SQL step in Example 9.16 totals the sales for each of six sections in the bookstore, producing an extract of six rows. The SELECT statement and the INTO clause save the six section names and six formatted total sales values in twelve macro variables.

In this example, it is known that BOOKS.YTDSALES has six section values. Example 9.19 shows a way to write the INTO clause if you do not know the number of values the SELECT clause will return.

proc sql noprint;

  select section, sum(saleprice) format=dollar10.2

  into :section1 - :section6,

       :sale1 - :sale6  from books.ytdsales

  group by section;

quit;

%put *** 1: &section1 &sale1;

%put *** 2: &section2 &sale2;

%put *** 3: &section3 &sale3;

%put *** 4: &section4 &sale4;

%put *** 5: &section5 &sale5;

%put *** 6: &section6 &sale6;

The SAS log showing the execution of the %PUT statements follows:

95   %put *** 1: &section1 &sale1;

*** 1: Certification and Training $16,227.32

96   %put *** 2: &section2 &sale2;

*** 2: Networking $11,353.04

97   %put *** 3: &section3 &sale3;

*** 3: Operating Systems $15,963.34

98   %put *** 4: &section4 &sale4;

*** 4: Programming $10,160.95

99   %put *** 5: &section5 &sale5;

*** 5: Software $29,374.98

100  %put *** 6: &section6 &sale6;

*** 6: Web Development $12,065.77

Example 9.17: Storing All Unique Values of a Table Column in One Macro Variable with PROC SQL

A feature of the INTO clause allows you to store all values of a column in one macro variable. These values are stored side by side. To do this, add the SEPARATED BY option to the INTO clause to define a character that delimits the string of values.

The PROC SQL SELECT statement in Example 9.17 stores all unique section names in the macro variable ALLSECT.

proc sql noprint;

  select unique(section)

  into :allsect separated by '/'

  from books.ytdsales

  order by section;

quit;

%put The value of macro variable ALLSECT is &allsect;

The SAS log showing the execution of the %PUT statement follows:

6681  %put The value of macro variable ALLSECT is &allsect;

The value of macro variable ALLSECT is Certification and Training/Networking/Operating Systems/Programming/Software/Web Development

Example 9.18: Storing All Values of a PROC SQL Dictionary Table Column in One Macro Variable

Example 9.18 is similar to Example 9.17 in that it saves all values of a column in one macro variable, but this example does not apply the UNIQUE function. Example 9.18 makes use of the DICTIONARY tables feature of PROC SQL. It saves in one macro variable DATASETNAMES the names of all the SAS data sets in a library specified by the value of macro variable LISTLIB. A blank separates the data set names assigned to DATASETNAMES. Assume there are three SAS data sets in library BOOKS: YTDSALES, SALES2013, and SALES2012.

%let listlib=BOOKS;

proc sql noprint;

  select memname

  into :datasetnames separated by ' '

  from dictionary.tables

  where libname=“&listlib”;

quit;

%put The datasets in library &listlib is(are) &datasetnames;

The SAS log showing the execution of the %PUT statement follows:

6720  %put The datasets in library BOOKS is(are) &datasetnames;

The datasets in library BOOKS is(are)

SALES2012 SALES2013 YTDSALES

Using the Macro Variables Created by PROC SQL

PROC SQL creates and updates four macro variables after it executes each statement. You can use these macro variables in your programs to control execution of your SAS programs. These macro variables are stored in the global macro symbol table. Table 9.2 lists the four PROC SQL macro variables.

Table 9.2 Macro variables created by PROC SQL

Macro Variable

Description

SQLEXITCODE

Contains the highest return code that occurred from some types of SQL insert failures. This return code is written to the SYSERR macro variable when PROC SQL terminates.

SQLOBS

Set to the number of rows produced with a SELECT statement

SQLRC

Set to the return code from an SQL statement

SQLOOPS

Set to the number of iterations of the inner loop of PROC SQL

The pass-through facility of PROC SQL also creates two macro variables, SQLXMSG and SQLXRC. These macro variables contain information about error conditions that might have occurred in the processing of pass-through facility SQL statements. For complete information on these macro variables, refer to SAS/ACCESS documentation. Table 9.3 describes the two macro variables.

Table 9.3 PROC SQL macro variables used with the pass-through facility

Macro Variable

Description

SQLXMSG

Set to descriptive information and DBMS-specific return code  generated by a pass-through facility SQL statement

SQLXRC

Set to the return code generated by a pass-through facility SQL statement

Example 9.19: Using the PROC SQL SQLOBS Automatic Macro Variable

Macro program LISTSQLPUB in Example 9.19 uses the SQLOBS macro variable to list the values of a series of macro variables that were created by a SELECT statement and the INTO clause. The goal of the program is to save the names of the publishers in BOOKS.YTDSALES in a series of macro variables.

The INTO clause contains only the reference to the first macro variable in the PUB series of macro variables. This reference is followed by a dash (-). This structure tells SAS to create a macro variable for each value that the SELECT clause returns. The number of publishers in BOOKS.YTDSALES is 12. The SELECT statement returns twelve values and saves the values in macro variables PUB1-PUB12.

After the SELECT statement executes, PROC SQL updates the SQLOBS macro variable. The iterative %DO loop uses this value as its upper index value. The %PUT statement in the iterative %DO loop lists each publisher’s name.

Depending on the complexity of your programming, you might want to save the value of SQLOBS in another macro variable after that PROC SQL step ends. This would prevent loss of the SQLOBS value you need in case you submit other SELECT statements before you execute code that references that original SQLOBS value.

options mprint;

%macro listsqlpub;

  proc sql noprint;

    select unique(publisher)

      into :pub1 -  

    from books.ytdsales;

  quit;

  %put Total number of publishers: &sqlobs..;

  %do i=1 %to &sqlobs;

    %put Publisher &i: &&pub&i;

  %end;

%mend listsqlpub;

%listsqlpub

The SAS log after LISTSQLPUB executes follows:

MPRINT(LISTSQLPUB):   proc sql;

MPRINT(LISTSQLPUB):   select unique(publisher) into :pub1 -

from books.ytdsales;

MPRINT(LISTSQLPUB):   quit;

NOTE: PROCEDURE SQL used (Total process time):

      real time           0.04 seconds

      cpu time            0.04 seconds

Total number of publishers: 12.

Publisher 1: AMZ Publishers

Publisher 2: Bookstore Brand Titles

WARNING: Apparent symbolic reference LEE not resolved.

Publisher 3: Doe&Lee Ltd.

Publisher 4: Eversons Books

Publisher 5: IT Training Texts

Publisher 6: Mainst Media

Publisher 7: Nifty New Books

Publisher 8: Northern Associates Titles

Publisher 9: Popular Names Publishers

Publisher 10: Professional House Titles

Publisher 11: Technology Smith

Publisher 12: Wide-World Titles

If you specify an upper limit on the series of macro variables on the INTO clause that is less than the number of values that the SELECT clause returns, SAS still executes the step. In this situation, SAS creates only the number of macro variables that are specified, which is 2, and assigns the first values it returns to those macro variables.

MPRINT(LISTSQLPUB):   proc sql noprint;

MPRINT(LISTSQLPUB):   select unique(publisher) into :pub1 - :pub2 from books.ytdsales;

MPRINT(LISTSQLPUB):   quit;

NOTE: PROCEDURE SQL used (Total process time):

      real time           0.03 seconds

      cpu time            0.03 seconds

Total number of publishers: 2.

Publisher 1: AMZ Publishers

Publisher 2: Bookstore Brand Titles

If you specify an upper limit on the series of macro variables INTO clause that is greater than the number of values that the SELECT clause returns, SAS creates only the number of macro variables equal to the number of values that the SELECT clause returns. This SAS log shows that the upper limit is set to 100.

MPRINT(LISTSQLPUB):   options symbolgen;

MPRINT(LISTSQLPUB):   proc sql noprint;

MPRINT(LISTSQLPUB):   select unique(publisher) into :pub1 - :pub100 from books.ytdsales;

MPRINT(LISTSQLPUB):   quit;

NOTE: PROCEDURE SQL used (Total process time):

      real time           0.03 seconds

      cpu time            0.00 seconds

MPRINT(LISTSQLPUB):   options nosymbolgen;

Total number of publishers: 12.

Publisher 1: AMZ Publishers

Publisher 2: Bookstore Brand Titles

WARNING: Apparent symbolic reference LEE not resolved.

Publisher 3: Doe&Lee Ltd.

Publisher 4: Eversons Books

Publisher 5: IT Training Texts

Publisher 6: Mainst Media

Publisher 7: Nifty New Books

Publisher 8: Northern Associates Titles

Publisher 9: Popular Names Publishers

Publisher 10: Professional House Titles

Publisher 11: Technology Smith

Publisher 12: Wide-World Titles

A %PUT statement verifies that there is no PUB13 macro variable.

186  %put &pub13;

WARNING: Apparent symbolic reference PUB13 not resolved.

&pub13

Displaying Macro Option Settings with PROC SQL and Dictionary Tables

Using PROC SQL, you can obtain information about your SAS session by accessing dictionary tables. These read-only SAS data views contain such information as option settings, librefs, member names and attributes in a library, and column names and attributes in a table or data set. Example 9.18 used a dictionary table to capture the names of all the data sets in a specific library and saved that information in one macro variable.

One dictionary table, OPTIONS, provides information about the current settings of SAS system options including macro facility related options. Another dictionary table, MACROS, provides information about macro variables including their scope and values. With these dictionary tables, you can access information about your current SAS session and programmatically use that to control execution of your SAS programs.

Example 9.20: Accessing Macro Option Settings with PROC SQL and Dictionary Tables

The OPTIONS dictionary table contains current settings and descriptions for SAS system options. A column in the table, GROUP, assigns a category to the setting. One group is MACRO. To display the current settings of the options in the MACRO group, submit the following code.

proc sql;

  select * from dictionary.options

  where group='MACRO';

quit;

The PROC SQL step that follows saves the setting of the macro option MINDELIMITER in a macro variable MYSETTING.

options mindelimiter='#';

proc sql noprint;

  select setting

  into :mysetting

  from dictionary.options

  where optname='MINDELIMITER';

quit;

%put My current MINDELIMITER setting is &mysetting;

The SAS log after submitting the preceding program follows.

62   %put My current MINDELIMITER setting is &mysetting;

My current MINDELIMITER setting is #

The PROC SQL step illustrates a simple example in working with the MACRO group of the dictionary tables. However, it might be much easier to simply submit the following %LET statement to define macro variable MYSETTING.

%let mysetting=%sysfunc(getoption(mindelimiter));

Example 9.21: Accessing Macro Variable Characteristics with PROC SQL and Dictionary Tables

The dictionary table MACROS contains information about macro variables. Included in this table are the macro variables that you create as well as automatic variables created by SAS. To display the list of macro variables currently defined in your session, submit the following PROC SQL step.

proc sql;

  select * from dictionary.macros;

quit;

As seen earlier in this book, submitting the following statement would display much of the same information.

%put _all_;

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.142.146