I'm still new to SAS and DB2. I have a DB2 Table with a column that stores values encoded as timestamps. I'm trying to load data onto this column from a SAS data set in my Work directory. Some of these timestamps, however, correspond to dates before 01-01-1582 and can not be stored as datetime values in SAS. They are instead stored as strings.
This means that if I want to load these values onto the DB2 table I must first convert them to timestamp with the TIMESTAMP() DB2 function, which, as far as I know, requires passthrough SQL with an execute statement (as opposed to the SAS ACCESS libname method). For instance, in order to write a single value I do the following:
PROC SQL;
connect to db2 (user = xxxx database = xxxx password = xxxx);
execute (insert into xxxx.xxxx (var) values (TIMESTAMP('0001-01-01-00.00.00.000000'))) by db2;
disconnect from db2;
quit;
How can I achieve this for all values in the source data set? A select ... from statement inside the execute command doesn't work because as far as I know I can't reference the SAS Work directory from within the DB2 connection.
Ultimately I could write a macro that executes the PROC SQL block above and call it from within a data step for every observation but I was wondering if there's an easier way to do this. Changing the types of the variables is not an option.
Thanks in advance.
A convoluted way of working around that would be to use call execute
:
data _null_;
set sas_table;
call execute("PROC SQL;
connect to db2 (user = xxxx database = xxxx password = xxxx);
execute (
insert into xxxx.xxxx (var)
values (TIMESTAMP('"||strip(dt_string)||"'))
) by db2;
disconnect from db2;
quit;");
run;
Where sas_table
is your SAS dataset containing the datetime values stored as strings and in a variable called dt_string
.
What happens here is that, for each observation in a dataset, SAS will execute the argument of the execute
call routine, each time with the current value of dt_string
.
Another method using macros instead of call execute to do essentially the same thing:
%macro insert_timestamp;
%let refid = %sysfunc(open(sas_table));
%let refrc = %sysfunc(fetch(&refid.));
%do %while(not &refrc.);
%let var = %sysfunc(getvarc(&refid.,%sysfunc(varnum(&refid.,dt_string))));
PROC SQL;
connect to db2 (user = xxxx database = xxxx password = xxxx);
execute (insert into xxxx.xxxx (var) values (TIMESTAMP(%str(%')&var.%str(%')))) by db2;
disconnect from db2;
quit;
%let refrc = %sysfunc(fetch(&refid.));
%end;
%let refid = %sysfunc(close(&refid.));
%mend;
%insert_timestamp;
EDIT: I guess you could also load the table as-is in DB2 using SAS/ACCESS and then convert the strings to timestamp with sql pass-through. Something like
libname lib db2 database=xxxx schema=xxxx user=xxxx password=xxxx;
data lib.temp;
set sas_table;
run;
PROC SQL;
connect to db2 (user = xxxx database = xxxx password = xxxx);
execute (create table xxxx.xxxx (var TIMESTAMP)) by db2;
execute (insert into xxxx.xxxx select TIMESTAMP(dt_string) from xxxx.temp) by db2;
execute (drop table xxxx.temp) by db2;
disconnect from db2;
quit;