I would like to input a list of tables as a macro parameter.
Macro Code:
%MACRO Marco_Name ( Table_Name ) ;
PROC SQL;
execute (
select (owner ||'.'||table_name) as table_name from dba_tables
where table_name in (&Table_Name.)
)
QUIT;
%MEND Marco_Name ;
When I would invoke the macro with e.g.:
%Marco_Name ( Table_Name = 'table1', 'table2, 'table3')
I would like to the code to resolve to:
select (owner ||'.'||table_name) as table_name from dba_tables
where table_name in ('table1', 'table2, 'table3')
Welcome to the wonderful world of marco programming.
The %STR macro function is used to wrap values containing commas that would otherwise confound the macro processor when passed as parameters.
Invoke the macro as follows:
%MyMacro ( Table_Name = %str ( 'table1', 'table2, 'table3' ) )
Related
how to use macro to change names of a table column ,except the ones that you point out.numeric type columns are added prefix "XC_" and char type columns are added prefix "XN_"
A proper utility macro will accept all the processing abstractions as parameters:
data=, the data set to operate on
copy=, the variables to leave alone (copy is an homage to the copy statement in TRANSPOSE)
char_prefix=XC_, prefix to apply to names of not-copied character variables, default is XC_
num_prefix=XN_, prefix to apply to names of not-copied numeric variables, default is XN_
The innards of a utility macro is a black box. Sometimes the design of the innards are specified to allow DATA and PROC steps to occur.
Sample code
Proc SQL is used to fill a macro variable with a list of old=new name pairs that can be used in a RENAME statement executed by Proc DATASETS
%macro Fixer ( data=, copy=, char_prefix=XC_, num_prefix=XN_ );
%let syslast = &data;
%local lib mem rename_clause;
%let lib = %scan(&syslast,1);
%let mem = %scan(&syslast,2);
proc sql noprint;
select
trim(name) || '=' ||
case type
when 'num' then "&num_prefix" || name
when 'char' then "&char_prefix" || name
else ''
end
into :rename_clause separated by ' '
from
dictionary.columns
where
libname = "&lib"
and memname = "&mem"
and indexw (%upcase("©"), upcase(name)) = 0
;
proc datasets nolist;
modify &data;
rename &rename_clause;
run;
quit;
%mend;
data class;
set sashelp.class;
teacher = 'Davidowski';
run;
options mprint;
%Fixer ( data=class, copy=Name )
Other times the innards must not generate any code. For this question such a macro would use macro function %SYSFUNC to access data set functions such as open, close, attrn, vartype, varname as it tests renaming criteria and accumulates old=new name pairs that will be emitted for use by the callee.
I want to store count of dataset in variable like below
%let Cnt ;
create table work.delaycheck as
select * from connection to oracle
(
SELECT PTNR_ID,CLNT_ID,REPORTING_DATE_KEY,NET_SALES
FROM FACT_TABLE
MINUS
SELECT PTNR_ID,CLNT_ID,REPORTING_DATE_KEY,NET_SALES
FROM HIST_FCT
);
I want to store count of this table in the variable Cnt like below
%put = (Select count(*) from work.delaycheck )
And Then
If(Cnt=0)
THEN
DO NOTHING
ELSE
execute(
Insert into Oracle_table
select * from work.delaycheck
) by oracle;
disconnect from oracle;
quit;
How can I acheive these steps? Thanks In advance!!
All of the SQL and data shown is occurring remotely. You can perform all the activity there without involving SAS. Oracle will process
PROC SQL;
CONNECT TO ORACLE ...;
EXECUTE (
INSERT INTO <TARGET_TABLE>
SELECT * FROM
( SELECT PTNR_ID,CLNT_ID,REPORTING_DATE_KEY,NET_SALES
FROM FACT_TABLE
MINUS
SELECT PTNR_ID,CLNT_ID,REPORTING_DATE_KEY,NET_SALES
FROM HIST_FCT
)
) BY ORACLE;
and not insert any records if the fact table is comprised of only historical facts.
EXECUTE can also submit PL/SQL statements, which in-turn can reduce the need for extraneous system interplay.
Delete this line from your code
%let Cnt ;
In order to get the count: Add the code below which will create the macro variable Cnt with the count:
proc sql;
Select count(*) into: Cnt from work.delaycheck ;
quit;
Update the if statement: the "&" is used to reference macro variables
If &cnt=0
The Code below shows how to use the if/else and the use of Call Execute:
data _null_;
if &cnt=0 then put 'Cnt is 0';/*if true: a note is written to the log*/
else call execute ('proc print data=work.e; run;');
/*else clause: the Proc Print code is executed*/
run;
I have a SAS macro below that is not working--- this snippet returns no values because the where statement doesn't work. Anyone have any ideas? I tried adding %str but that didn't work either.
%macro refreshments(beverage_type=);
proc sql;
select
*
where drink_type = '&beverage_type.'
;
quit;
%mend
%refreshments(Sprite);
Thanks.
Macro variables will not resolve in single quotes. You are also missing the FROM clause, and the macro parameter was being provided as positional (instead of name=value pair). Try the following:
%macro refreshments(beverage_type=);
proc sql;
select *
from YOURTABLE
where drink_type = "&beverage_type";
%mend;
%refreshments(beverage_type=Sprite);
I would like to delete the last 3 letters from a set of variables in a SAS dataset.
(have to concatenante 2 datasets. )
And in the first set, the variables are named for example:
abc ,
def ,
ghi ...
While in the 2nd set they are named:
abc_1A ,
def_1A ,
ghi_1A ...
How can I delete the '_1A' from the 100+ variables? I don't want to simply add '_1A' to my first Dataset
Thanks
There are a few options. Here is one 'safe' option and one 'unsafe' option.
Safe option:
Write a macro to rename a variable to its name without the _1A.;
Arguments: var = variable name, len = length desired of final variable name.;
%macro rename_shorter(var=,len=);
&var. = %substr(&var.,1,&len.)
%mend rename_shorter;
Create a list of calls from dictionary.columns;
proc sql;
select cats('%rename_shorter(var=',name,',len=',length(name)-3,')')
into :renamelist separated by ' '
from dictionary.columns
where libname='SASHELP' and upcase(memname)='CLASS';
quit;
Call that list;
data want;
set sashelp.class(rename=(&renamelist.));
run;
An unsafe option, in the sense that it doesn't check that things are aligned correctly, is
proc sql;
create table want as
select * from have_namedright H
outer union corr
select * from have_namedwrong W
;
quit;
I need to call a macro code from proc sql in SAS like below.
PROC SQL;
CONNECT TO DB2 (SSID = &DGSYS);
CREATE TABLE <DS_NAME> AS
SELECT * FROM CONNECTION TO DB2
(
SELECT * FROM <TAB_NAME> WHERE...
);
%MACRO_CODE(....) --> am calling a macro block of code here
DISCONNECT FROM DB2;
QUIT;
But this is throwing up an error. Could this not be done?
When I used a macro variable in my query it is allowing me but not a call made to macro code.
The macro would create another macro variable which will be an IN CLAUSE holding values from the previously created table/dataset. And it would be subsequently used in the another CREATE TABLE... in side the same PROC SQL.
If I understand correctly, it sounds like a macro isn't necessary for what you're doing. If you're creating a macro variable containing a list of values from a dataset, you can just use the INTO: clause.
ds_name : Table with numeric and alphanumeric variables.
proc sql noprint;
/* If VAR_NAME is numeric, this works */
select distinct var_name
into: listvals
separated by " "
from ds_name;
/* If VAR_NAME is character, do this instead */
select distinct cats("'",varname,"'")
into: listvals
separated by " "
from ds_name;
create table new_ds as
select *
from another_ds
where var_name in (&listvals);
quit;
I hope that helps.