How to use schema in DMBS SAS connection - sql-server

Below script show me table dbo.calendar in SAS:
LIBNAME SQL ODBC DSN='sql server' ;
PROC PRINT DATA=SQL.calendar;
RUN;
When I changed DATA to SQL.dbo.calendar (this is a correct name from SQL Server), I got:
6032 PROC PRINT DATA=SQL.dbo.calendar;
ERROR: Invalid data set name SQL.dbo.calendar.
Why and how to choose other schemas in SAS?

The default schema is defined in the DSN. Use the SCHEMA= option in the LIBNAME Statement
LIBNAME SQL ODBC DSN='sql server' schema=<something other than default> ;
http://support.sas.com/documentation/cdl/en/acreldb/69039/HTML/default/viewer.htm#p0bu3zsz1a08ton1msxdx1jo45np.htm

Related

SQL to SAS ODBC connection - truncation of NVARCHAR(max) but getting ERROR: The option dbtype is not a valid output data set option

I have a table stored in SQL Server Management Studio version 15.0.18369.0 and I have a working and established ODBC connection to SAS language program World Programming Software version 3.4.
Previous import/reading of this data has been successful but the operator of the SQL server may have recently converted their data type to NVARCHAR(max). It may also be due to a driver change (I got a new laptop and reinstalled what I thought was the exact same OBDC for SQl driver as I had before but who knows) I have 64-bit ODBC Driver 17 for SQL server.
The VARCHAR(max) type in SQL causes the data to only be 1 character long in every column.
I have tried to fix it by:
Adding the DB max text option to libname
libname odbclib odbc dsn="xxx" user="xxx" password="xxx" DBMAX_TEXT=8000;
This did nothing so I also tried to add DB type option:
data mydata (dbtype=(mycol='char(25)')) ;
set odbclib.'sql data'n
run;
And I get ERROR:
The option dbtype is not a valid output data set option.
I have also tried DBSASTYPE, and putting both options in the set statement and this yields the same error.
I also tried with proc SQL:
proc sql noprint;
CONNECT TO ODBC(dsn="xxx" user="xxx" password="xxx"); create table
extract(compress=no dbsastype=(mycol='CHAR(20)')) as select * from
connection to odbc ( select * from dbo.'sql data'n
); disconnect from odbc; quit;
And I get
NOTE: Connected to DB: BB64 (Microsoft SQL Server version 12.00.2148)
NOTE: Successfully connected to database ODBC as alias ODBC. 3915
create table extract(compress=no
dbsastype=(mycol='CHAR(20)')) as 3916 select *
from connection to odbc 3917 ( 3918 select *
from dbo.'sql data'n ERROR: The option dbsastype is not a valid
output data set option 3919 3920 ); 3921
disconnect from odbc; NOTE: ERRORSTOP was specified. The statement
will not be executed due to an earlier error NOTE: Statements not
executed because of errors detected 3922 quit;
One thing to try would be putting the DBTYPE or DBSASTYPE in the right place.
data mydata;
set odbclib.'sql data'n(dbtype=(mycol='char(25)'));
run;
It is an option that would go on the "set" not the "data" line.
I would also encourage you to contact the developers, as it seems like this is a bug in their implementation; or perhaps try a different ODBC SQL driver.
Maybe a workaround in the meanwhile is to use CONVERT in the passthrough?
proc sql noprint;
CONNECT TO ODBC(dsn="xxx" user="xxx" password="xxx"); create table
extract as select * from
connection to odbc ( select a,b,c,convert(NCHAR(20),mycol) from dbo.'sql data'n
); disconnect from odbc; quit;

Mapping an SQL server library in SAS

I'm trying to map the source of a dataset i usually access using SQL parse through as a library.
Below is the SQL parse through code I use to access the table
proc sql noprint;
connect to ODBC (DSN='Location1' );
create table test as
Select *
from Connection to ODBC
(
Select *
from CentralDB.dbo.Table_i_want
)
;
disconnect from ODBC
;
quit;
And below is the libname statement I tried writing
LIBNAME mylib ODBC DATASRC='Location1' SCHEMA=dbo ;
The above statement doesn't map it to the correct location, where do I put the CentralDB part?
Can anyone help me create a libname statement out of this?
Thanks,
libname mydblib odbc
noprompt="uid=testuser;pwd=testpass;dsn=sqlservr;"
stringdates=yes;
proc print data=mydblib.customers;
where state='CA';
run;
If you have a metadata server: It is always better to ask your SAS Admin to register the library and tables you want want in SAS metadata / Folders so you will have a permanent and standard way to access them.
Quick Solution:
Use the libname below and update the schema, user and password
LIBNAME mylib ODBC DATASRC=location_1 SCHEMA=dbo USER=sql user PASSWORD="xxx" ;
The step below will list the tables in the library
proc datasets lib=mylib ;
quit;
I always opt to build a connection string. I don't have an example on hand, but you should be able to build a string that specifies both the database CentralDB and the schema dbo.
It will look something like this:
libname mylib odbc noprompt='Driver={SQLServer};Server=Your_Server_Name; Database=CentralDB;Schema=dbo;Uid=Your_Username; Pwd=Your_Password;';

WHERE clause operator requires compatible variables

Below script (fx is SQL Server's table):
LIBNAME SQL ODBC DSN='sql server' ;
DATA new;
SET SQL.fx;
WHERE repo_date = '2016-04-29 00:00:00.000';
RUN;
PROC PRINT DATA=new;
RUN;
returns me an error (in SAS log):
191 WHERE repo_date = '2016-04-29 00:00:00.000';
ERROR: WHERE clause operator requires compatible variables.
192 RUN;
Where can I check which data conversion I need (in this case and in others)?
In SQL Server 2008R2 repo_date is a datetime column.
You are comparing a string to a numeric value.
So your datetime-format is wrong (like Heinzi mentioned), and also you have to convert it to a datetime value (by adding a dt at the end)
Working should this:
WHERE repo_date ='29APR2016 00:00:00.000'dt;
If repo_time is datetime and the time is not relevant, you can just compare the date:
WHERE datepart(repo_date) = '29APR2016'd;
SAS is using the ODBC libname engine to translate SAS data step code into SQL code. Because you're writing it in SAS, SAS is assuming that you are looking for the string 2016-04-29 00:00:00.000. Instead, you want to put it in a SAS date literal so SAS knows how to translate the data.
LIBNAME SQL ODBC DSN='sql server' ;
DATA new;
SET SQL.fx;
WHERE repo_date = '29APR2016:00:00:00'dt;
RUN;
PROC PRINT DATA=new;
RUN;
If you were doing SQL passthrough to directly run SQL on the server, then your above code would work.
proc sql noprint;
connect to odbc(datasrc='sql server');
create table new as
select * from connection to odbc
(select * from schema.fx where repo_date='2016-04-29 00:00:00.000');
disconnect from odbc;
quit;
Basically, what the above is doing is having the SQL server pull the columns, then SAS simply pulls it all over to itself. Think of it as using SAS as a proxy program to run commands directly on the SQL server.

Insert Date Field to MS SQL from Proc SQL

I'd like to insert a date field into a SQL server table form Proc SQL in SAS. Here is my code for Proc SQL:
proc sql;
insert into CFS_SQL.Data_DSB_Raw(sasdatefmt=(TheDate='mmddyy10.'))
select TheDateIncoming
from Work.Upload;
quit;
According to the SAS help documentation (http://support.sas.com/kb/6/450.html), this should work as long as TheDateIncoming also has format mmddyy10.. I've verified that the format on TheDateIncoming is correct, so I think this should work.
Unfortunately, however, I'm getting a "Value 1 on the SELECT clause does not match the data type of the corresponding column" error.
Any thoughts?
Annnnnd... solved. It actually had nothing to do with the code. It was a driver problem. Switching to the SQL Server Native Client 11.0 ODBC driver fixed the issue.

Fully Qualified Names from SQL Server in SAS

I need to be able to specify the schema that I want to access in SAS. I have used a connection string with the following schema=?? but SAS will not let me select or print the contents of any object in the named schema. Has anyone been able to write a PROC SQL statement selecting objects in a schema other than dbo?
Thank you,
SAS does not use fully quallified names from the SQL server but you can direct SAS to a specific schema. The following is an example that uses a libname as connection to a 2008 SQL Server.
proc print data=myDBconn.v_Lots (SCHEMA=SAS);
WHERE Study_ID IS NOT NULL;
run;
proc print data=myDBconn.Drugs (SCHEMA=Pharmacy);
where _drug_id=1;
run;
proc sql;
create table myTest.drugs as ;
(SELECT * FROM myDbconn.drugs (SCHEMA=Pharmacy));
quit;

Resources