Sas process sql - 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"
);

Related

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;

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

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.

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

Use macro variables in Proc SQL in SAS

Two macro variables are defined for table schema and table name and they are used in the proc sql statement in SAS (postgresql interface to Amazon RedShift), sql statement can't be read correctly.
%let table_schema = 'sales';
%let table_name = 'summary_table';
proc sql;
connect to ODBC(DSN='redshift_db', user=masteruser password='*pwd');
create table column_names as
select * from connection to odbc(
select distinct(column_name) as col_name from information_schema.columns where table_schema = &table_schema and table_name = &table_name;
);
create table dt as
select * from connection to odbc(
select * from &table_schema..&table_name;
);
QUIT;
The first table creation throws an error:
ERROR: CLI describe error: ERROR: column "summary_table" does not exist in columns;
The "summary_table" actually exists.
The second table creation throws an error:
ERROR: CLI describe error: ERROR: syntax error at or near "'sales'"; No query has been executed with that handle
which is invalid either.
Check your syntax.
Look at the ERROR: column "summary_table" does not exist in columns;
What that is saying is that the COLUMN named "summary_table" does not exist on the table named "columns". The where clause is trying to compare 2 columns, not a column and a string.
Write the query without macros and get that to work. Then attempt to put the macros in.
This is a syntax issue with the PostGreSQL ODBC driver, not SAS.
I haven't used the PostGreSQL driver before but I know different DBs handle quotes differently. It may be that PostGreSQL wants double quotes instead of single. If this is the case then I would change your code like so:
%let table_schema = sales;
%let table_name = summary_table;
proc sql;
connect to ODBC(DSN='redshift_db', user=masteruser password='*pwd');
create table column_names as
select * from connection to odbc(
select distinct(column_name) as col_name from information_schema.columns where table_schema = "&table_schema" and table_name = "&table_name";
);
create table dt as
select * from connection to odbc(
select * from &table_schema..&table_name;
);
QUIT;
Note that I've removed the single quotes from the %let statments and added double quotes to the where clause in the first query.
Removing the singles quotes from the macro vars will also fix the syntax error you are experiencing with the second query as you were effectively trying to do the following:
select * from 'sales'.'summary_table';
... which is most likely not correct. Again I haven't used PostGreSQL so I can't say for certain - please correct me if I'm wrong and that is correct syntax for it.
Finally, I'd recommend that when working with macro variables in general, that you don't put single quotes around your strings. ie.
%let table_schema = 'sales'; * AVOID THIS WHEN POSSIBLE;
vs
%let table_schema = sales; * USE THIS APPROACH WHEN POSSIBLE;
Put double quotes around the places where macro vars are used instead and you'll probably find things a little easier. Of course there's always circumstances where you may want quotes in the value of the macro variable, but as a general rule of thumb I avoid doing this whenever possible.

How to get existence of a temporary table in sql server 2008

I wrote this query:
SELECT * INTO #nima FROM Region r
Every time I execute this queries:
SELECT OBJECT_NAME(OBJECT_ID('tempdb..#nima'))
--or
SELECT OBJECT_NAME(OBJECT_ID('#nima'))
I get NULL, but when I execute above select I get error that #nima alreadty exist
Try just using the OBJECT_ID function to determine if the temp table exists:
SELECT object_id('tempdb..#nima')
Or if you wish to retrieve the object name, you will need to specify the database id using the DB_ID function for the temp database:
SELECT OBJECT_NAME(OBJECT_ID('tempdb..#nima'), DB_ID('tempdb'))
This gives the internal id of #nima as expected in tempdb
SELECT OBJECT_ID('tempdb..#nima'))
OBJECT_NAME takes a local database ID. There will be no object (except by rare chance) with that ID locally because the ID comes from tempdb
Demo (untested!)
USE tempdb
SELECT OBJECT_NAME(OBJECT_ID('tempdb..#nima')) --#nima + system generated stuff
USE MyDB
SELECT OBJECT_NAME(OBJECT_ID('tempdb..#nima')) --null
-- Now we add DBID for tempdb
SELECT OBJECT_NAME(OBJECT_ID('tempdb..#nima'), 2) -- #nima + system generated stuff