SAS libname odbc, how to access a two-level name table - odbc

I recently found the libname statement is very handy to access tables reside in odbc. But I don't know how to access those tables having a two-level names. Below is an example.
Old code I use (this code works):
proc sql;
connect to odbc(dsn=edw_nz user=&username. pw=&password.);
create table test select * from connection to odbc(
select *
from EDW_XYZ_PROD01..Table_xyz);
quit;
Now, I want to use the libname facility to access the odbc:
libname edw odbc database=edw_nz user=&username. pw=&password.;
proc sql;
create table test as
select *
from edw.EDW_XYZ_PROD01..Table_xyz;
quit;
I got this error:
ERROR 22-322: Syntax error, expecting one of the following: a name, (, ), ',', ANSIMISS, AS, CROSS, EXCEPT, FULL, GROUP, HAVING, INNER, INTERSECT, JOIN, LEFT, NATURAL, NOMISS, OUTER, RIGHT, UNION, WHERE.
ERROR 200-322: The symbol is not recognized and will be ignored.
Any one can help?
Thanks a lot!

SAS cannot handle 3 level names.
You need to specify the schema/database inside the libname section. You have a few options (read the doc for all the options).
We use ODBC to connect to our SQL server instances like this:
libname pdata odbc complete='DSN=SQLServerProd;Database=MyDatabase';
The complete= option allows you specify the full ODBC connection string. This should allow you to specify the database/schema.

Is EDW_XYZ_PROD01 a schema or something?
I think you might have to specify that on the datasource= option. For example:
libname mydblib odbc user=testuser password=testpass datasrc=mydatasource;

Have you tried the schema= option on the libname statement. The schema is equivalent to the first level name.
libname edw odbc database=edw_nz user=&username. pw=&password. schema=edw;
proc sql;
create table test as
select *
from EDW_XYZ_PROD01..Table_xyz;
quit;

Related

Pass .sql file into DBI::dbGetQuery with comments as the first line into R / RStudio

I am trying to pass a .sql file into DBI::dbGetQuery, but I run into problems whenever there is comment in the first line. For example:
runs_fine.sql
SELECT * FROM mytable
does_not_work.sql
-- Some comment
SELECT * FROM mytable
Then in R:
library(odbc)
library(tidyverse)
con <- dbConnect(odbc(), "my_connection")
dbGetQuery(con, read_file("sql/runs_fine.sql")) # success
dbGetQuery(con, read_file("sql/does_not_work.sql")) # fails
Motivation: I would like to leverage the convenient sql preview function from RStudio, but this requires the first line be the following for any .sql file:
-- !preview conn=con
...which causes the dbGetQuery to fail. I suppose a workaround would be to use some sort of read.file function that can skip lines or avoid comment lines.
NOTE: If a comment line is in the middle of a .sql file, dbGetQuery succeeds as expected and avoids the appropriate commented lines.
DBMS is CHD Impala, kerberized. The return value from read_file() begins with:
"-- !preview conn=con\r\n\r\nSELECT \r\n ..."

Create a dataset with a stored procedure with two databases for rdlc report VS2015

I want add a new Datasets to my rdlc report in VS 2015, so I created a new data source with my stored procedure. There it is :
CREATE PROCEDURE [dbo].[getAccidents]
(#p_anneeDebut date, #p_anneeFin date)
AS
SELECT *
FROM T_ACCIDENT
LEFT OUTER JOIN TJ_ACC_PAR ON TJ_ACC_PAR.ACC_id = T_ACCIDENT.ACC_id AND TJ_ACC_PAR.ACC_type = T_ACCIDENT.ACC_type AND TJ_ACC_PAR.ACC_annee = T_ACCIDENT.ACC_annee
LEFT OUTER JOIN TR_PARTIE_CORPS ON TJ_ACC_PAR.PAR_id = TR_PARTIE_CORPS.PAR_id
LEFT OUTER JOIN TR_BLESSURE ON TJ_ACC_PAR.BLE_id = TR_BLESSURE.BLE_id
LEFT OUTER JOIN ERP.dbo.TR_COST_CENTER ON TR_COST_CENTER.COS_id = T_ACCIDENT.ACC_lieuPrecis
WHERE ACC_date <= #p_anneeFin AND ACC_date >= #p_anneeDebut
But when I add this new data source, it does not appears in the list "Data Source" so I can't select it for my report. ( The data source is well created ).
I tested with other stored procedure and it works, the problem is this line (because without this line it works too) :
LEFT OUTER JOIN ERP.dbo.TR_COST_CENTER ON TR_COST_CENTER.COS_id = T_ACCIDENT.ACC_lieuPrecis
Because this line call an other database but the query works in SQL SERVER.
How can I solve my problem ?
Have you tried running you stored proc from the Sql server, maybe its the Collation between the two databases which is different, that is if the join is on a string value. If you are calling a stored proc in SSRS the best trouble shoot is to first get the results in SSMS and if an error comes up you can easily troubleshoot. Plus try using alias on your Joins.

Create a stored procedure using RMySQL

Background: I am developing a rscript that pulls data from a mysql database, performs a logistic regression and then inserts the predictions back into the database. I want the entire system to be self contained in the script in case of database failure. This includes all mysql stored procedures that the script depends on to aggregate the data on the backend since these would be deleted in such a database failure.
Question: I'm having trouble creating a stored procedure from an R script. I am running the following:
mySQLDriver <- dbDriver("MySQL")
connect <- dbConnect(mySQLDriver, group = connection)
query <-
"
DROP PROCEDURE IF EXISTS Test.Tester;
DELIMITER //
CREATE PROCEDURE Test.Tester()
BEGIN
/***DO DATA AGGREGATION***/
END //
DELIMITER ;
"
sendQuery <- dbSendQuery(connect, query)
dbClearResult(dbListResults(connect)[[1]])
dbDisconnect(connect)
I however get the following error that seems to involve the DELIMITER change.
Error in .local(conn, statement, ...) :
could not run statement: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DELIMITER //
CREATE PROCEDURE Test.Tester()
BEGIN
/***DO DATA AGGREGATION***/
EN' at line 2
What I've Done: I have spent quite a bit of time searching for the answer, but have come up with nothing. What am I missing?
Just wanted to follow up on this string of comments. Thank you for your thoughts on this issue. I have a couple Python scripts that need to have this functionality and I began researching the same topic for Python. I found this question that indicates the answer. The question states:
"The DELIMITER command is a MySQL shell client builtin, and it's recognized only by that program (and MySQL Query Browser). It's not necessary to use DELIMITER if you execute SQL statements directly through an API.
The purpose of DELIMITER is to help you avoid ambiguity about the termination of the CREATE FUNCTION statement, when the statement itself can contain semicolon characters. This is important in the shell client, where by default a semicolon terminates an SQL statement. You need to set the statement terminator to some other character in order to submit the body of a function (or trigger or procedure)."
Hence the following code will run in R:
mySQLDriver <- dbDriver("MySQL")
connect <- dbConnect(mySQLDriver, group = connection)
query <-
"
CREATE PROCEDURE Test.Tester()
BEGIN
/***DO DATA AGGREGATION***/
END
"
sendQuery <- dbSendQuery(connect, query)
dbClearResult(dbListResults(connect)[[1]])
dbDisconnect(connect)

RODBC Error for CURRENT_TIMESTAMP() - is there a list of acceptable keywords?

I submitted a simple (so I thought) query via RODBC :
ch <- odbcConnect(dsn.name, believeNRows=FALSE, rows_at_time=1)
sqlQuery(ch, "CURRENT_TIMESTAMP()")
And it threw the following error:
[1] "42000? -1 Malformed SQL Statement: Unrecognized keyword: CURRENT_TIMESTAMP\r\nStatement:CURRENT_TIMESTAMP()"
[2] "[RODBC] ERROR: Could not SQLExecDirect 'CURRENT_TIMESTAMP()'"
I thought CURRENT_TIMESTAMP() is a common SQL command and didn't expect this to not run. I had checked that the ODBC connection (RSSBus DynamicsCRM Source x64) supports CURRENT_TIMESTAMP(). My connection is OK, I was able to perform some other SQL queries.
So is there a problem with my syntax above? Or is there a list of keywords that RODBC doesn't recognise?
In the above code, first line i.e.
ch <- odbcConnect(dsn.name, believeNRows=FALSE, rows_at_time=1)
creates a connection to your ODBC data source name (dsn.name). So here ch basically stores the connection instance. The second line:
sqlQuery(ch, "CURRENT_TIMESTAMP()")
executes the SQL query on the connection i.e. ch and returns the result in a data frame. So instead of using the method CURRENT_TIMESTAMP() use complete query:
sqlQuery(ch, "SELECT CURRENT_TIMESTAMP()")
I hope this will help.

What's the easiest way to use SQLite with SAS?

I want to investigate how to access SQLite DB from SAS. What's the easiest way of doing this? Is there a SAS product that we can license to do that? I don't want to use ODBC drivers as that seems to have been written a long time ago and is not officially part of SQLite.
SAS supports reading data from pipes (in a unix environment). Essentially, you can set up a filename statement to execute an sqlite command in the host environment, then process the command output as if reading it from a text file.
SAS Support page: http://support.sas.com/documentation/cdl/en/hostunx/61879/HTML/default/viewer.htm#pipe.htm
Example:
*----------------------------------------------
* (1) Write a command in place of the file path
* --> important: the 'pipe' option makes this work
*----------------------------------------------;
filename QUERY pipe 'sqlite3 database_file "select * from table_name"';
*----------------------------------------------
* (2) Use a datastep to read the output from sqlite
*----------------------------------------------;
options linesize=max; *to prevent truncation of results;
data table_name;
infile QUERY delimiter='|' missover dsd lrecl=32767;
length
numeric_id 8
numeric_field 8
character_field_1 $40
character_field_2 $20
wide_character_field $500
;
input
numeric_id
numeric_field $
character_field_1 $
character_field_2 $
wide_character_field $
;
run;
*----------------------------------------------
* (3) View the results, process data etc.
*----------------------------------------------;
proc contents;
proc means;
proc print;
run;

Resources