SAS: Insert a value into a macro variable from connection to ODBC - sas

I'm trying to get DDL from Redshift tables' catalog.
Using the below method is the only way I know to insert a value into a macro variable.
proc sql noprint;
connect to odbc(&_OUTPUT_connect.);
SELECT ddl into :a trimmed from connection to ODBC
( SELECT 'CREATE OR REPLACE VIEW ' + n.nspname + '.' + c.relname + ' AS\n' + COALESCE(pg_get_viewdef(c.oid, TRUE), '') AS ddl
FROM
pg_catalog.pg_class AS c
INNER JOIN
pg_catalog.pg_namespace AS n
ON c.relnamespace = n.oid
WHERE n.nspname||'.'||c.relname in ('ditemp.depend_test1' ,'ditemp.depend_test2' ,'ditemp.depend_test3','ditemp.depend_test4')
);
disconnect from odbc;
quit;
But it doesn't work (hangs).
Are there any other method to do the above?

Related

Sql to proc sql conversion

I have 2 tables that contains var values like (ID, date, var1,var2,var3....)
I need to get the data from table2 and add it to table1 for which (ID or date) does not exist in table1.
I am using the below code in sql to get new ID's from tab2 to tab1:
INSERT INTO table1
SELECT * FROM table2 a
WHERE ID not in(select ID from table1 where ID=a.ID)
Here is the code to add new date for existing ID's in tab2 to tab1 :
INSERT INTO table1
SELECT * FROM table2 a
WHERE date not in(select date from table1 where ID=a.ID)
I don't know how to do this in proc sql.
Please share an effective method to do this task.
To insert the new ID I used:
proc sql;
create table lookup as
select a.ID
from table1 a inner join table2 b
on a.ID = b.ID
;
insert into table1
select * from table2 a
where a.ID not in (select ID from lookup)
;
quit;
This works well. But, it failed to insert a date for existing IDs.
Please suggest some ideas to complete this step.
Thanks in advance!
SAS SQL is Similar to the SQl you have written.
The SAME insert statements can be warped as proc sqls in SAS and they work like charm.
If your SQL did work then the following will work too.
PROC SQL;
INSERT INTO work.table1
SELECT * FROM work.table2 a
WHERE ID not in(select ID from work.table1 where ID=a.ID);
INSERT INTO work.table1
SELECT * FROM work.table2 a
WHERE date not in(select date from work.table1 where ID=a.ID)
QUIT;

How to assign a Count of dataset to variable and use it in IF ELSE statement

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;

Indexing on temporary tables in Azure SQL Data Warehouse

Does Azure SQL Data Warehouse support any indexing on temporary tables? No mention of the limitation is found at https://learn.microsoft.com/en-us/azure/sql-data-warehouse/sql-data-warehouse-tables-temporary.
In one attempt at such, I received:
Cannot create a non-clustered index on a temporary table.
Does that wording infer a clustered index can be placed on a temporary table?
At one of my project usage temporary tables with indexes at several columns and with option adding new columns to them was quite critical to for me. (ALTER TABLE is also not supported for temp tables). The standard table was not the option as each query run had to have own table.
Finally, I used something that can be used as temporary tables but in fact is not a temporary table. I'm creating a standard table but with Guid as name and assign the name to a variable. So instead of #TempTable I'm using #MySemiTempTable but that work only for generated code. So I have to run that code using sp_executesql. Bellow example:
declare #MySemiTempTable NVARCHAR(MAX)
declare #sql NVARCHAR(MAX)
set #MySemiTempTable = 'TMP_' + CAST(NEWID () AS NVARCHAR(37))
set #sql = 'CREATE TABLE ['+ #MySemiTempTable + '] (Column1 [int], Column2 NVARCHAR(50))'
EXECUTE sp_executesql #sql
set #sql = 'INSERT INTO ['+ #MySemiTempTable + '] VALUES (1, ''test1'')'
EXECUTE sp_executesql #sql
set #sql = 'create unique index column1 on ['+ #MySemiTempTable + '] (column1)'
EXECUTE sp_executesql #sql
set #sql = 'select * from ['+ #MySemiTempTable + '] '
EXECUTE sp_executesql #sql
set #sql = 'drop table ['+ #MySemiTempTable + '] '
EXECUTE sp_executesql #sql
Clustered indexes are supported on temp tables. For example:
CREATE TABLE #temp_table
(
c1 integer
,c2 integer
)
WITH ( CLUSTERED INDEX (c1 ASC) )
;

How to order columns created using Proc SQL in SAS

I am using Proc SQL to create Teradata views. I used Execute (pass through facility) and passed the column names as using variables. But the views which are getting created do not have the columns in the order which was passed into the query. They are getting created at any random order. Is there a way to fix this?
Using the method described here:
data tmp;
aa = 1;
db = 1;
ac = 1;
bb = 1;
run;
proc sql ;
select name into :VARLIST separated by ', '
from dictionary.columns
where libname = 'WORK'
and memname = 'TMP'
order by name ;
quit ;
proc sql ;
create table ordered as
select &VARLIST
from work.tmp ;
quit ;
Not familiar with Teradata per se, more used to working with SAS/DB2, but what if instead of using execute() you would use something like this -- this will create the view on the SAS side (which might not be what you're after, I'm not entirely sure).
proc sql;
connect to teradata (user=testuser password=testpass);
create view work.myView as
select * from connection to teradata
(select var1, var2, var3
from someTable);
quit;

SAS: How do I write a pass-through to Teradata query without bringing back the results?

I want write a passthrough query in SAS but I don't want to bring back the results and I want to store the results in Teradata.
In Teradata SQL I can do
create table db.table2 as (select
column1,
column2,
count(*) as cnt
from
db.table1
group by
column1, column2
having cnt = 1) with data primary index(column1, column2)
)
In SAS there is only examples of pass-through query that returns some results into SAS. In this case I just want to use SAS to create a table on Teradata without leaving the SAS interface (I can do this in Teradata Studio Express) but it breaks the workflow.
How do I do a "pass-through" without returning the results? The below doesn't seem to work. What's the right for what I want to do?
PROC SQL;
CONNECT TO TERADATA(user="user" password="pw" server ="Teradata.something.somehwere");
drop table teradata.sometable ;
DISCONNECT FROM TERADATA;
QUIT;
You need the EXEC statement:
PROC SQL;
CONNECT TO TERADATA(user="user"
password="pw"
server ="Teradata.something.somehwere");
EXEC( ) BY TERADATA;
EXEC( Commit ) BY TERADATA; /* this is needed if the above statement modifies the database in anyway) */
drop table teradataserver.sometable ;
DISCONNECT FROM TERADATA;
QUIT;
Within the brackets you can insert a Teradata SQL statement that will run on the DB and keep the results on the DB. So, in full:
PROC SQL;
CONNECT TO TERADATA(user="user"
password="pw"
server ="Teradata.something.somehwere");
EXEC(
create table db.table2 as
(
select
column1,
column2,
count(*) as cnt
from
db.table1
group by
column1, column2
having cnt = 1
) with data primary index(column1, column)
) BY TERADATA;
DISCONNECT FROM TERADATA;
QUIT;
For info, the BY part specifies which DB to process the statement on, if we were connecting to more than one DB within the SQL Procedure, e.g.
PROC SQL;
CONNECT TO TERADATA AS T1 (...);
CONNECT TO TERADATA AS T2 (...);
EXEC(...) by T1;
EXEC(...) by T2;
DISCONNECT FROM T1;
DISCONNECT FROM T2;
QUIT;