Calling Oracle Stored Procedure from SAS - sas

How can I call an Oracle stored proc from SAS to pass values and return values. I have SAS/ACCESS and running SAS 9.3
Thanks
Dan

This should work:
proc sql;
connect to oracle (user="oracleUserName" password="pass" path="serverPath" CONNECTION=GLOBAL CONNECTION_GROUP = SASAML);
execute( execute MyPackage.MyProcedure(&param1, &param2) ) by oracle;
/* param1 and param2 are macro variables here */
disconnect from oracle;
quit;

This should work fine in SAS 9.2 and above using ODBC passthrough.
Here's a similar discussion with relevant links:
http://communities.sas.com/message/114296#114296
I'll try and come back sometime to surmise the linked article in this answer...

Pass-through stored procedure execution does not support output parameters. But if you need only one output parameter, a workaround is to use a function and "SELECT FROM dual" query. Here is in example (it uses one input parameter that is passed in from a macro variable).
%let a = 'ddd';
proc sql;
connect to oracle as ora2 (user=xxx password=xxx path="xxx");
select * from connection to ora2 (
SELECT test_fun(p_a => &a.) FROM dual
);
disconnect from ora2;
run;

Related

SAS/ACCESS Interface to Teradata QUERY_BAND

SAS Libname Statment
QUERY_BAND= LIBNAME Option
Generate
SET QUERY_BAND="BAND;" FOR SESSION;
I need to generate this :
SET QUERY_BAND='BAND’; FOR SESSION VOLATILE;
Whitch statment should I to use?
Statement like QUERY_BAND_VOLATILE does not exist.
Your query_band expression is incorrect. Use smth like below, and run it within the Proc SQL as Richard suggested.
SET QUERY_BAND = 'BAND=1;' FOR SESSION VOLATILE;
proc sql;
connect to teradata as tdd (server=&SERVER. user=&HCUSER. password=&HCPASS.);
execute(SET QUERY_BAND = 'BAND=1;' FOR SESSION VOLATILE; ) by tdd;
disconnect from tdd;
quit;

SAS : Select rows from a relationnal database

I work with SAS on a relationnal database that I can access with a libname odbc statement as below :
libname myDBMS odbc datasrc="myDBMS";
Say the database contains a table named 'myTable' with a numeric variable 'var_ex' which values can be 0,1 or . (missing). Now say I want to exclude all rows for which var_ex=1.
If I use the following :
DATA test1;
SET myDBMS.myTable; /* I call directly the table from the DBMS */
where var_ex NE 1;
run;
I don't get rows for which 'var_ex' is missing. Here is a screenshot of the log, with my actual data :
Whereas if I do the exact same thing after importing the table in the Work :
DATA myTable; /* I put myTable in the Work library */
SET myDBMS.myTable;
run;
DATA test2;
SET myTable; /* I call the table from the work */
where var_ex NE 1;
run;
I select rows for which 'var_ex' is 0 or missing, as intended. Here is a screenshot of the log, with my actual data :
The same happens if I use PROC SQL instead of a DATA step, or another NE-like.
I did some research and more or less understood here that unintended stuff like that can happen if you work directly on a DBMS table.
Does that mean is it simply not recommended to work with a DBMS table, and one has to import table locally as below before doing anything ?
DATA myTable; /* I put myTable in the Work library */
SET myDBMS.myTable;
run;
Or is there a proper way to manipulate such tables ?
The best way to test how SAS is translating the data step code into database code is through the sastrace system option. Before running code, try this:
options sastrace=',,,db' sastraceloc=saslog;
Then run your code tests. When you check the log, you will see precisely how SAS is translating the code (if it can at all). If it can't, you'll see,
ACCESS ENGINE: SQL statement was not passed to the DBMS, SAS will do the processing.
followed by a select * from table.
In general, if SAS cannot translate data step code into dbms-specific code, it will pull everything to locally manipulate the data. By viewing this output, you can determine precisely how to get the data step to translate into what you need.
If all else fails, you can use explicit SQL pass-through. The code in parentheses operates the same way as if you're running SQL directly from some other client.
proc sql;
connect to odbc(datasrc='source' user='username' pass='password');
create table want as
select * from connection to odbc
(<code specific to your dbms language>);
disconnect from odbc;
quit;

how to get the return codes from SAS pass-through SQL to Teradata ?

In SAS 9.2, how do I get the return codes / error messages from explicit pass-through sql to teradata? Printed in log or output or something.
I already got a small query to work fine, but having some trouble with a more complex one. Debugging would be much easier with the error messages.
Tried the sqlxmsg and sqlxrc that are used when querying db2, but of course those don't work... haven't found any documentation on this. (I'm quite new to Teradata)
Use the SASTRACE option to bring back debugging messages from Teradata.
http://support.sas.com/documentation/cdl/en/acreldb/63647/HTML/default/viewer.htm#a000433982.htm
This document supports and shows an example of it in use on explicit pass-through SQL:
https://support.sas.com/resources/papers/TroubleshootingSASandTeradataQueryPerformanceProblems.pdf
N.B. If you are using this option on large sets of data, be careful to choose the options wisely or you will create huge logs
This was the code, and now after shutting and restarting SAS it works fine!
Seems I had some process hanging somewhere...
rsubmit sashost;
proc sql;
connect to teradata (user=&terauser password=&terapass server=&teraserv mode=teradata);
create table test as
select * from connection to teradata
(select x
from y.z
where c);
%put &sqlxmsg;
%put &sqlxrc;
disconnect from teradata;
quit;
proc download data=test out=locallib.test; run;
endrsubmit;

Sql Query into Access database(.accdb)

I'm using right now , and its working, a proc sql to connect to my DB(access .accdb). Until now I was only using it to do SELECT query. Here is a example that work and that I use to do so.
proc sql;
/* create an ODBC pass-through connection using the Microsoft Office Access 2007 .accdb driver */
connect to ODBC as savesdb
(required="driver=Microsoft Access Driver (*.mdb, *.accdb); dbq=&dir_BD.;");
create table MYTABLE as select * from connection to savesdb(select MYID from ACCESSTABLE);
/* close the pass-through connection */
disconnect from savesdb;
quit;
Now I want to execute a INSERT INTO query. I know that the next code is working
execute( INSERT INTO ACCESSTABLE ( MYID ) VALUES ( 1 )) by savesdb;
The thing is in the INSERT INTO I want to specify to insert the values that are in a dataset. In other word I have a dataset with 4 records so I want to call my insert into 4 times with the values in dataset.
Is there a way to do so?
All you need to do is loop through the DataSet in a data step and read the columns to a macro variable.. one var for each column.
then call the proc sql code with these macro variables as input to the macro definition which will do the insert into DB using full pass through.
however as pointed out libref is the easier method.
Thanks,
Manish

How does " into" work on proc sql?

This is PROC SQL. Could anyone explain what I am getting as output ? Thanks !
proc sql;
select time into :date from end_date;
quit;
In addition to Chris J's answer, the INTO clause has a very versatile functionality. The following resources will give you very good overview.
Essentially using the INTO clause you can create a macro variable which holds a lists of items seperated by a custom delimiter, create a whole host of macro variables inside a single PROC SQL procedure - a task which could take multiple DATA _NULL_ steps & PROC SORT\MEANS\FREQ steps etc...
It is the PROC SQL equivalent of using %let date = <some time value>; or inside a datastep
DATA _NULL_;
set end_date;
call symputx("date", time);
RUN;
Using the Magical Keyword "INTO:" in PROC SQL
SAS(R) 9.2 Macro Language: Reference: INTO Clause
It simply puts the result into a macro variable, in this case the macro variable 'DATE' contains the time value off the record in the dataset end_date.