SAS - using proc imported CSV in proc SQL (error) - sql

I am looking to connect a CSV dataset I imported through 'proc import' with a dataset I am pulling from proc sql. Is there a way to toss my proc import file into proc sql? or vice versa?
here is where I'm at:
proc import datafile = 'filepath'
out = dataname
dbms = CSV
replace
;
run;
proc sql
connect to netezza as dbcon
(server="url" database=sandbox user=me password="&password.");
create table work as
select distinct * from connection to dbcon
(
select distinct a.*
from
dataname as a
left join
sqltable as b
on
a.number = b.number
);
quit;
I am currently receiving this error message but I am unsure where my syntax is wrong:
ERROR: CLI prepare error: ERROR: relation does not exist database.ADMIN.dataname
SQL statement: select distinct a.*, b.* from dataname as a left join sqltable as b on a.number and b.number.

After you connect to Netezza using the CONNECT TO statement, anything you have inside brackets such as:
select ... from connection to dbcon (...);
exec (...) by dbcon;
Is inside the Netezza box. The dataset you created called dataname is present in the work library where your SAS Session is running.
So the question can be solved in a few ways:
Upload data to Netezza
Use the libname Netezza engine to connect
Create the table in Netezza using Insert into in SAS
Libname engine
You can usually translate a connect to statement into a libname statement as follows:
libname dbcon netezza server="url" database=sandbox user=me password="&password.";
If you create dataname in the dbcon library then your second query should work, provided you have permissions to create tables in the sandbox database.

Related

deleting tables from postgresql without raising cross-database references are not implemented: using pandas/psycopg2

I am trying to drop a table from a database.
As long as name_Table is a structured as
schema.table
it all works nicely. However, I do have one table in public schema.
When I try to delete it as:
public.subname.table
I get this answer:
cross-database references are not implemented: "public.subname.table"
How to drop public.subname.table?
print('Connecting to the PostgreSQL database...')
postgresConnection = psycopg2.connect(
host=XXXXXX,
port=YYYYYYYYY,
database="mydb",
user=os.environ['user'],
password=os.environ['pwd'])
cursor = postgresConnection.cursor()
dropTableStmt = "drop TABLE %s;"%name_Table;
# Create a table in PostgreSQL database
print(dropTableStmt)
cursor.execute(dropTableStmt)
postgresConnection.commit()
cursor.close();
print('Database cursor closed.')
postgresConnection.close()
print('Database connection closed.')
public.subname.table runs afoul of Identifier rules in that '.' is not a valid character. The way around that is to double quote the identifier e.g. "public.subname.table" or use the function quote_ident like quote_ident(public.subname.table). In your case drop TABLE quote_ident(%s).
UPDATE
Previous solution was not. I did not test it and just assumed. A tested solution:
--In psql
create table "public.subname.table"(id int);
select * from "public.subname.table";
id
----
(0 rows)
--In Python
import psycopg2
from psycopg2 import sql
con = psycopg2.connect(dbname="test", host='localhost', user='postgres')
cur = con.cursor()
cur.execute(sql.SQL("DROP table {table}").format(table=sql.Identifier("public.subname.table")))
con.commit()
--psql
select * from "public.subname.table";
ERROR: relation "public.subname.table" does not exist
LINE 1: select * from "public.subname.table";
This makes use of the psycopg2 sql module to properly and safely quote the table name in a query string.
DROP TABLE public."subname.table" does what you want.
sql.Identifier("public", "subname.table") is what you want as psycopg2 identifier.

How to query SSMS via SAS EG ODBC connection while using data from WORK?

Is there a way to send a SAS dataset through a proc sql odbc query in SAS EG so that it can be taken in and used by SQL server?
ex)
SAS Data WORK.A contains 3 columns ID, col1, col2.
I have a table in Sql Management Studio environment with the same ID column.
I would like to (somehow) do as shown in Figure A below:
Figure A)
proc sql;
Connect to odbc("driver=SQL Server; database=SSMSDatabase; Server=SSMSServer");
create table WORK.B as
select * from connection to odbc
(
Select t1.*, t2.*
from SSMSTable1 t1
INNER JOIN WORK.A t2 ON t1.ID = t2.ID
);
disconnect from odbc;
quit;
This throws an obvious error in SAS as SSMS doesn't understand what WORK.A is... It's expecting pure SSMS code to be executed.
I have passed macro variables created in SAS through to SQL passthrough to be used in the WHERE statement like in figure B, but that has it's limitations (especially with macro character length) and is not as elegant as passing a whole table.
Figure B)
proc sql;
select cat("'",trim(ID),"'")
into :list1 separated by ","
from WORK.A;
quit;
%macro ODBCRun();
proc sql;
Connect to odbc("driver=SQL Server; database=SSMSDatabase; Server=SSMSServer");
create table WORK.B as
select * from connection to odbc
(
Select *
from SSMSTable1
WHERE ID IN (&list1.)
);
disconnect from odbc;
quit;
%mend;
%ODBCRun();
Any ideas would be helpful.
Create a temporary table in SQL Server, against which you can perform your later pass through query.
Example:
libname SS odbc
dbmstemp=yes
noprompt="driver=SQL Server; database=SSMSDatabase; Server=SSMSServer"
;
* upload SAS data into SQL Server;
proc delete data=ss.'#idlist'n;
run;
data ss.'#idlist'n;
set WORK.A;
run;
* Use uploaded data in pass through query;
proc sql;
connect using SS as REMOTE; * reuses connection libref made;
create table WORK.B as
select * from connection to REMOTE
(
select t1.*, t2.*
from
SSMSTable1 t1
INNER JOIN
#idlist t2
ON
t1.ID = t2.ID
);
disconnect from REMOTE;
quit;

How to use SAS data set brought to SQL Server temporary table and use with another temp table to join,update

Using SAS Enterprise Guide Version 7.1 64 bit.
I cannot create base tables in SQL Server thus can only create temporary table for data processing.
I am also pulling data over from a SAS data set to a global temporary table as(the SAS data set is teradata table pushed to sas-(step2). I need to update holiday table.
I also cannot see how many records are updated in the log (if there is a way to get it, it will be helpful as that way i know the code is working) - I have the sastraceloc but that is not showing update counts in a table.
I finally need to update ##t1 (step4) table created in step 1 with fields from ##holidays table (step2), how do I code this? Am I using the execute, proc sql combination correctly?
Step #1
LIBNAME tmpdta ODBC DATAsrc=datasrcname INSERTBUFF=32767
USER='uid' PASSWORD="pwd" connection=shared;
LIBNAME loc '/c/folder/data';
PROC SQL exec noerrorstop;
CONNECT TO odbc as test(DSN=datasrcname USER='uid' PASSWORD="pwd" connection=shared;
connection=shared);
execute
(create table ##t1
id int,
name varchar(50),
address varchar(100)
)by test;
-- end of 1
step #2
data tmpdt.'##holidays'n;
set loc.holidayexpns;
run;
step #3
proc sql;
connect using tmpdt;
execute
(
update u SET
fee=0,
month=5
FROM tmpdt.##holidays u
)by tmpdt;
step #4
PROC SQL exec noerrorstop;
CONNECT TO odbc as test(DSN=datasrcname USER='uid' PASSWORD="pwd" connection=shared;
connection=shared);
execute
(
update xyz
set a.fee=b.fee,
a.month=b.month
from tmpdt.##holidays h
join ##t1 xyz on
h.id=xyz.id
)by test;
The execute native-query will not know the SAS reference tmpdt., tmpdt will be known to your user login only if on the SQL Server side you have access to a catalog of like name. Did you mean to indicate tempdb ?
Per documentation
Any return code or message that is generated by the DBMS is available in the macro variables SQLXRC and SQLXMSG after the statement completes.

Passing a value from Netezza back to SAS using a macro variable

we're using SAS 7.13 HF1 (7.100.3.5419) (64-bit)
I'm currently looking at a post that shows how to pass a value from SAS to a database that you're connecting in to. Here is the example below. You can see they take the Macro variable StartDate and pass it into Teradata to be used in the query.
%let StartDate = 2016/01/01;
proc sql;
connect to teradata
(BULKLOAD=YES MODE=TERADATA user=&user. Password=&passwd.);
CREATE TABLE WorkTest.test AS
select * from connection to teradata
(
SELECT
TOP 10 *
FROM SomeCalendarData
WHERE SomeDate = %bquote('&StartDate.');
);
quit;
I want to go the other way.
How can I read a value from a similar query, only my DB is Netezza, and somehow pass it to a macro variable in SAS?
Thanks!
You would use the
SELECT <expression> INTO :<macro_var>'
statement. This is available in the PROC SQL query but not in the pass-through code, so it would look something like
proc sql;
connect to teradata
(BULKLOAD=YES MODE=TERADATA user=&user. Password=&passwd.);
select somedate into :my_macro_var from connection to teradata
(
SELECT somedate
FROM SomeCalendarData
WHERE id = 101;
);
quit;
See the docs here: http://support.sas.com/documentation/cdl/en/sqlproc/63043/HTML/default/viewer.htm#n1tupenuhmu1j0n19d3curl9igt4.htm

Sas process sql

I am trying to select from a SQL server table that both has dashes in the name and is greater than 32 characters.
I have tried pass through and quotes but no joy.
It's very unlikely that I could get a view produced and only have read access.
proc sql;
drop table poss_gw1;
create table poss_gw1 as ( select * from cdb.'''form_Garden_waste_service_AF-Form-59fb9946-0f6e-4cd9-‌​9b30-82fc5d96ec71'''‌​n as agg);
quit;
proc sql;
connect to odbc(dsn=FirmstepReporting user=myname pwd=mypwd);
Create table work.tmp_gw as select * from connection to odbc (select * from "'form_Garden_waste_service_AF-Form-59fb9946-0f6e-4cd9-9b30-‌​82fc5d96ec71'"n);
disconnect from odbc;
quit;
Any one have any ideas?
You need to use SQL Server syntax in the pass thru code.
create table work.tmp_gw as
select * from connection to odbc
(select *
from "form_Garden_waste_service_AF-Form-59fb9946-0f6e-4cd9-9b30-‌​82fc5d96ec71"
);
If your variable names are also not valid for SAS then you will need to change the name in the pass thru code also.
create table work.tmp_gw as
select * from connection to odbc
(select id
, "invalid-name" as valid_name
from "form_Garden_waste_service_AF-Form-59fb9946-0f6e-4cd9-9b30-‌​82fc5d96ec71"
);