Can someone please help? I have not used SAS in a few years and need some assistance with connecting to Teradata.
I want to connect to Teradata using ACCT1 if the time of day is between 7pm-6:59am or with Acct2 if the time of day is between 7am-6:59pm.
%let
acct1="mismktdev"
acct2="mismktprod"
%include
%macro t_cnnct;
options nomprint;
connect to teradata (tdpid="&tpidxyz" user="&misuid"
password="&mispwd" account="&acct1" mode=teradata);
options mprint;
proc sql;
connect to teradata (user="&terauser" password="&terapwd" mode=teradata);
execute (SET QUERY_BAND = 'Application=PrimeTime;Process=Daily;script=pt_add_history_v30.sas;' for session ) by teradata;
%mend t_cnnct;
proc sql;
Sel * from tblname;
You can use %let timenow=%sysfunc(time(), time.); to get the time at which the program is running and then in you macro do something like :
%macro test();
%let timenow=%sysfunc(time(), time.);
%put &timenow;
%if (&timenow > '19:00'T and &timenow < '06:59'T) %then %do;
/* Your Code for 7pm - 6:59am Here*/
%end;
%else %do;
/*Code for 7am - 6:59pm here*/
%end;
%mend;
%test();
Your idea to use SAS macro variables is just right. Here is a macro to define all the global SAS macro variables you need (including changing the "account" string):
%macro t_cnnct;
%global tdserver terauser terapwd teraacct teradb;
%let tdserver=myTDPID;
%let terauser=myuserID;
%let terapwd=mYTDpassword;
%let teradb=myTDdatabase;
%let now=%sysfunc(time());
%if &now >= %sysfunc(inputn(07:00,time5.))
and &now <= %sysfunc(inputn(19:00,time5.))
%then %let teraacct=mismktdev;
%else %let teraacct=mismktprod;
%mend t_cnnct;
Note the SAS macro variable values are specified without double-quotes! Use double-quotes when they are referenced in your code.
Next, just run the macro before your PROC SQL code to set the variables and use those variables in your connect string:
%t_cnnct;
proc sql;
connect to teradata (user="&terauser" password="&terapwd" account="&teraacct"
server="&tdserver" mode=teradata);
execute (
SET QUERY_BAND = 'Application=PrimeTime;Process=Daily;script=pt_add_history_v30.sas;' for session
) by teradata;
create table mySASds as
select *
from connection to teradata (
select *
from &teradb..tablename
);
quit;
Note that the tdpid= option you were using is an alias for the server= option (which I prefer). Also, the query band you set will remain in effect for the entire PROC SQL run.
And here is an example of a SAS libref that uses the same macro variables:
libname myTD teradata user="&terauser" password="&terapwd" account="&teraacct"
server="&tdserver" database="&teradb" mode=teradata);
Related
I'm making a macro to pull tables from a database, then export some of those tables using proc export. I'm doing this by using an if-then-do statement to check if the macro variable equals a string, and if it does then that table gets exported. Here's my code:
%MACRO query(x);
proc sql;
connect using conn;
create table &x. as select * from connection to conn
(select *
from db.&x.);
disconnect from conn;
quit;
%if &x. = "AddressCategory" %then
%do;
proc export data = &x. outfile="C:\path\&x..txt" dbms=dlm replace; delimiter="|";
run;
%end;
%mend query;
%query(AddressCategory);
This produces a dataset named AddressCategory, but the export doesn't work. any ideas? Thanks!
then export some of those tables
Within the macro you likely don't want to check for the item to export by name. If you do, the macro will grow to contain a large number of ifs checking which argument is appropriate for export.
A better macro would have an additional export= parameter that defaults to 0, and the callee sets it to 1 for the data sets to be exported
%MACRO fetcher (
remoteLibref=conn,
remoteSchema=db,
object=,
outlib=work,
out=&object,
export=0,
outpath=C:\exports\&remoteSchema,
outname=&object
);
proc sql;
connect using &remoteLibref;
create table &outlib..&out as select * from connection to &remoteLibref
( select *
from &remoteSchema..&object
);
disconnect from &remoteLibref;
quit;
%if &export %then %do;
proc export
dbms=dlm
data=&outlib..&out.
replace outfile="&outpath.\&object..txt"
;
delimiter="|";
run;
%end;
%mend fetcher;
The invoke it for your various remote objects, specifying explicitly the ones to export
libname conn sqlserver … connection string … ;
%fetcher(object=AddressCategory, export=1)
%fetcher(object=AddressBook)
%fetcher(object=PreferenceCategory, export=1)
%fetcher(object=PreferenceItems)
%fetcher(object=PreferenceProperties)
%fetcher(object=Payouts, export=1)
%fetcher(object=Payouts, RemoteSchema=DBX, export=1, outname=hidden-payouts)
data classivar_1;
set classvar;
AnaClassVar=scan(scan(F2,1," "),2,".");
run;
proc sql;
select AnaClassVar into : MacClassVar separated by "#" from classivar_1 ;
select count(*) into: Count_classvar from classivar_1;
quit;
%put &MacClassVar.;
%put &Count_classvar.;
ods output variables=adsl_var;
proc contents data=ev.adsl;
run;
proc sql;
select variable into : AllVar separated by "#"
from adsl_var;
select count(*) into : Count_Allvar from adsl_var;
quit;
%put &Allvar.;
%put &Count_Allvar.;
**** set up Macro ClassAna to analyze the classified varialbes;
%macro ClassAna(datasets= );
%do i= 1 %to &Count_classvar.;
%do count=1 %to &Count_Allvar;
%if %sysfunc(find(%scan(&MacClassVar,&i,#),%scan(&AllVar,&count,#)))
%then %do;
%let Class_var&i.=%scan(&AllVar,&count,#);
%end;
%end;
%put &&Class_var&i..;
%end;
%Mend;
%ClassAna(datasets=sashelp.class)
When I submit the programme , the macro variable Class_var6 cannot be resolved.
But other macro variables can be resolved correctly.
The logs are in the picture.enter image description here
enter image description here
In %ClassAna you are conditionally creating the macro vars based on:
%if %sysfunc(find(%scan(&MacClassVar,&i,#),%scan(&AllVar,&count,#)))
%then %do;
That FIND is case sensitive by default. I think it will work if you make it case insensitive by adding the optional i parameter to FIND. Something like:
%if %sysfunc(find(%scan(&MacClassVar,&i,#),%scan(&AllVar,&count,#),i))
%then %do;
Or you could %upcase both variable lists and leave the FIND as is.
I have a dataset naming error_table as follows. All the variables are character
Errorno Error Resolution
001 login check
002 datacheck check
I wanted a logic that executes a sas program If the Errorno is not in 001 and 002. Else stop execution and display the error_table.
I tried the following
%macro test();
proc sql;
select trim(Error_No) into: num from error_table;
quit;
%if &num. not in ("001","002") %then %do;
%include "/path/dev/program.sas";
%end;
%else %do;
proc print data = error_table;
run;
%end;
%mend;
%test;
But, it is throwing an error.
Can anyone please correct the logic.
You need to watch out for the case when the SELECT returns zero rows. You should set a default value to the macro variable NUM.
Is your dataset variable numeric or character? Use the TRIMMED or SEPARATED BY clause instead of the TRIM() function to prevent spaces in the macro variable that is generated by the INTO clause.
%let num=NONE;
select Error_No into: num trimmed from error_table;
Remember that to the macro processor everything is a string so don't but quotes around the values you are trying to match unless they are actually part of the value.
%if NOT (&num. in (001,002)) %then %do;
Also to use the IN operator in macro code you need to make sure you have set the MINDELIMITER option.
I would sugest moving condition with error codes to proc sql.
proc sql;
select count(*) into :num_errors
from error_table
where Errorno in ("001", "002");
quit;
Then in macrovariable you have number of errors that are 001 or 002.
Next step is to check macro-condition:
%if &num_errors. > 0 %then %do;
%include "/path/dev/program.sas";
%end;
%else %do;
proc print data = error_table;
run;
%end;
%mend;
I have a very large number of datasets that are not consistently formatted - I am trying to read them into SAS and normalize them.
The basic need here is to locate a 'key column' that contains a certain string - from there I know what to do with all the variables to the left and right of that column.
The 'GREP' macro from the sas website (http://support.sas.com/kb/33/078.html) seems like it can handle this, but I need help adapting the code in the following ways:
1 - I only need to search one dataset at a time, already in the 'work' library.
2 - I need to capture the name of the variable (and the position number of it) that prints to the log at the end of this macro. This seems like it would be easy but it just returns the last column in the dataset instead of the (correct) column that prints to the log at the end.
Current code below:
%macro grep(librf,string); /* parameters are unquoted, libref name, search string */
%let librf = %upcase(&librf);
proc sql noprint;
select left(put(count(*),8.)) into :numds
from dictionary.tables
where libname="&librf";
select memname into :ds1 - :ds&numds
from dictionary.tables
where libname="&librf";
%do i=1 %to &numds;
proc sql noprint;
select left(put(count(*),8.)) into :numvars
from dictionary.columns
where libname="&librf" and memname="&&ds&i" and type='char';
/* create list of variable names and store in a macro variable */
%if &numvars > 0 %then %do;
select name into :var1 - :var&numvars
from dictionary.columns
where libname="&librf" and memname="&&ds&i" and type='char';
quit;
data _null_;
set &&ds&i;
%do j=1 %to &numvars;
if &&var&j = "&string" then
put "String &string found in dataset &librf..&&ds&i for variable &&var&j";
%end;
run;
%end;
%end;
%mend;
%grep(work,Source Location);
The log returns: "String Source Location found in dataset WORK.RAW_IMPORT for variable C" (the third), which is correct.
I just need usable macro variables equal to "C" and "3" at the end. This macro will be part of a larger macro (or a prelude to it) so the two macro variables need to reset with each dataset I run through it. Thanks for any help offered.
Please find the modification below, basically what I have done was to create global macro variables for dataset name and variable name which will feed as input to get the variable position using VARNUM function as below, ( change identified by **** )
%macro grep(librf,string);
%let librf = %upcase(&librf);
proc sql noprint;
select left(put(count(*),8.)) into :numds
from dictionary.tables
where libname="&librf";
select memname into :ds1 - :ds&numds
from dictionary.tables
where libname="&librf";
%do i=1 %to &numds;
proc sql noprint;
select left(put(count(*),8.)) into :numvars
from dictionary.columns
where libname="&librf" and memname="&&ds&i" and type='char';
/* create list of variable names and store in a macro variable */
%if &numvars > 0 %then %do;
select name into :var1 - :var&numvars
from dictionary.columns
where libname="&librf" and memname="&&ds&i" and type='char';
quit;
%global var_pos var_nm var_ds;
data _null_;
set &&ds&i;
%do j=1 %to &numvars;
**** ADDED NEW CODE HERE ****;
if &&var&j = "&string" then do; /* IF-DO nesting */;
call symputx("var_nm","&&var&j"); /*Global Macro variable for Variable Name */
call symputx("var_ds","&&ds&i"); /*Global Macro variable for Dataset Name */
put "String &string found in dataset &librf..&&ds&i for variable &&var&j";
%end;
run;
**** ADDED NEW CODE HERE ****;
%let dsid=%sysfunc(open(&var_ds,i)); /* Open Data set */
%let var_pos=%sysfunc(varnum(&dsid,&var_nm)); /* Variable Position */
%let rc=%sysfunc(close(&dsid)); /* Close Data set */;
%end;
%end;
%mend;
%grep(work,Source Location);
%put &=var_nm &=var_ds &=var_pos;
I am working on SAS in UNIX env and I want to view only the column name of a dataset. I have tried proc contents and proc print but both of them list a lot of other irrevelant information that I do not want as it fills up my putty screen and the information ultimately is lost.
I also tried to get this thing frm the sas metadata but that is not working either.
I tried :
2? proc sql;
select *
from dictionary.tables
where libname='test' and memname='sweden_elig_file_jul';
quit;
5?
NOTE: No rows were selected.
6?
NOTE: PROCEDURE SQL used (Total process time):
real time 0.27 seconds
cpu time 0.11 seconds
You're using the wrong dictionary table to get column names...
proc sql ;
select name
from dictionary.columns
where memname = 'mydata'
;
quit ;
Or using PROC CONTENTS
proc contents data=mydata out=meta (keep=NAME) ;
run ;
proc print data=meta ; run ;
Here's one I've used before to get a list of columns with a little bit more information, you can add the keep option as in the previous answer. This just demonstrates how to create a connection to the metadata server, in case that is useful to anyone viewing this post.
libname fetchlib meta
library="libraryName" metaserver="metaDataServerAddress"
password="yourPassword" port=1234
repname="yourRepositoryName" user="yourUserName";
proc contents data=fetchlib.YouDataSetName
memtype=DATA
out=outputDataSet
nodetails
noprint;
run;
For a pure macro approach, try the following:
%macro mf_getvarlist(libds
,dlm=%str( )
)/*/STORE SOURCE*/;
/* declare local vars */
%local outvar dsid nvars x rc dlm;
/* open dataset in macro */
%let dsid=%sysfunc(open(&libds));
%if &dsid %then %do;
%let nvars=%sysfunc(attrn(&dsid,NVARS));
%if &nvars>0 %then %do;
/* add first dataset variable to global macro variable */
%let outvar=%sysfunc(varname(&dsid,1));
/* add remaining variables with supplied delimeter */
%do x=2 %to &nvars;
%let outvar=&outvar.&dlm%sysfunc(varname(&dsid,&x));
%end;
%End;
%let rc=%sysfunc(close(&dsid));
%end;
%else %do;
%put unable to open &libds (rc=&dsid);
%let rc=%sysfunc(close(&dsid));
%end;
&outvar
%mend;
Usage:
%put List of Variables=%mf_getvarlist(sashelp.class);
Returns:
List of Variables=Name Sex Age Height Weight
source: https://github.com/sasjs/core/blob/main/base/mf_getvarlist.sas
proc sql;
select *
from dictionary.tables
where libname="TEST" and memname="SWEDEN_ELIG_FILE_JUL";
quit;