DBI::dbSendQuery fails with RJDBC::JDBC for SQL SERVER - r

When I run the insert statement with odbc driver everythings fine.
drv <- odbc::odbc()
conn <- createConn(drv, trusted_connection = T, dsn="mydsn", uid="myuid", pwd="mypwd")
DBI::dbSendQuery("INSERT INTO \"dbo\".\"testjdbc\" (d) values('4')")
When I run the select statement with jdbc everything is fine too:
drv <- RJDBC::JDBC(driverClass = "com.microsoft.sqlserver.jdbc.SQLServerDriver", classPath = "C:\\mssql-jdbc-7.0.0.jre8.jar")
conn <- DBI::dbConnect(drv, trusted_connection = T, url = "jdbc:sqlserver://myserver\\\\myinstance:1111;databaseName=mydatabasename", user="myuid", password="mypwd")
DBI::dbGetQuery(conn, "Select * from dbo.mytable")
and the connection for jdbc is valid:
drv <- RJDBC::JDBC(driverClass = "com.microsoft.sqlserver.jdbc.SQLServerDriver", classPath = "C:\\mssql-jdbc-7.0.0.jre8.jar")
conn <- DBI::dbConnect(drv, trusted_connection = T, url = "jdbc:sqlserver://myserver\\\\myinstance:1111;databaseName=mydatabasename", user="myuid", password="mypwd")
DBI::dbIsValid(conn) # TRUE
But when I try insert statement (the same like the first one) with jdbc driver like this:
drv <- RJDBC::JDBC(driverClass = "com.microsoft.sqlserver.jdbc.SQLServerDriver", classPath = "C:\\mssql-jdbc-7.0.0.jre8.jar")
conn <- DBI::dbConnect(drv, trusted_connection = T, url = "jdbc:sqlserver://myserver\\\\myinstance:1111;databaseName=mydatabasename", user="myuid", password="mypwd")
DBI::dbSendQuery(conn, "INSERT INTO \"dbo\".\"testjdbc\" (d) values('4')")
then I get the error:
Error in .verify.JDBC.result(r, "Unable to retrieve JDBC result set for ", :
Unable to retrieve JDBC result set for INSERT INTO "dbo"."testjdbc" (d) values('4') (The statement did not return a result set.)
So jdbc select is OK but inserts, updates, deletes gives errors while with odbc I can do everything.

The solution is to run inserts not with DBI::dbSendQuery but with RJDBC::dbSendUpdate.
Thank you #Mark Rotteveel for your answer. Thanks to you I have found the solution.

Related

Insert R dataframe into SQL (RODBC) - error table not found

I would like to drop my whole dataframe from R preferably using RODBC with sqlSave statement (not sqlQuery). Here is my sample code.
library(RODBC)
myconn <- odbcDriverConnect("some connection string")
mydf <- data.frame(col_1 = c(1,2,3), col_2 = c(2,3,4))
sqlSave(myconn, mydf, tablename = '[some_db].[some_schema].[my_table]', append = F, rownames = F, verbose=TRUE)
odbcClose(myconn)
After I execute it, I get back error message:
Error in sqlColumns(channel, tablename) :
‘my_table’: table not found on channel
When I check in SQL Server, an empty table is present.
If I run the same code again, I get error message:
Error in sqlSave(myconn, mydf, tablename = "[some_db].[some_schema].[my_table]", :
42S01 2714 [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]There is already an object named 'my_table' in the database.
[RODBC] ERROR: Could not SQLExecDirect 'CREATE TABLE [some_db].[some_schema].[my_table] ("col_1" float, "col_2" float)'
Any suggestions on how to troubleshoot?
UPDATE
In SSMS I can run the following commands successfully:
CREATE TABLE [some_db].[some_schema].[my_table] (
test int
);
drop table [some_db].[some_schema].[my_table]
Here are details of connection string:
Driver=ODBC Driver 17 for SQL Server; Server=someserveraddress; Uid=user_login; Pwd=some_password
To avoid the error, you could specify the database in the connection string:
Driver=ODBC Driver 17 for SQL Server; Server = someserveraddress; database = some_db; Uid = user_login; Pwd = some_password
and avoid using brackets:
sqlSave(myconn, mydf, tablename = 'some_schema.my_table', append = F, rownames = F, verbose=TRUE)

Write to Snowflake VARIANT column from R

I am trying to load data to snowflake using the following code, but getting an error.
con <- DBI::dbConnect(
drv = odbc::odbc(),
driver = "SnowflakeDSIIDriver",
server = "<>",
authenticator = 'externalbrowser',
warehouse = "<>",
database = "<>",
UID = "<>",
role = "<>"
)
DBI::dbAppendTable(con, name = DBI::Id(schema = "<>", table = "<>"), value = tmp[1:2,])
tmp was downloaded from Snowflake, the same table using RStudio:
```{sql connection=con, output.var = 'tmp'}
select top 10 *
FROM <>
```
The error seems to be stemming from a VARIANT column where I store a JSON string.
Error in new_result(connection#ptr, statement, immediate) :
nanodbc/nanodbc.cpp:1374: 22000: SQL compilation error:
Expression type does not match column data type, expecting VARIANT but got VARCHAR(2) for column FEATURES
I had this once and it was an invalid JSON (missing brackets somewhere). Probably this helps.

RPostgreSQL - Passing Parameter in R to a Query in RPostgreSQL

Question: How do I pass a variable in the RPostgreSQL query?
Example: In the example below I try to pass the date '2018-01-03' to the query
library(RPostgreSQL)
dt <- '2018-01-03'
connect <- dbConnect(PostgreSQL(),
dbname="test",
host="localhost",
port=5432,
user="user",
password="...")
result <- dbGetQuery(connect,
"SELECT * FROM sales_tbl WHERE date = #{dt}")
You can use paste0 to generate your query and pass it to dbGetQuery:
library(RPostgreSQL)
dt <- '2018-01-03'
connect <- dbConnect(PostgreSQL(),
dbname="test",
host="localhost",
port=5432,
user="user",
password="...")
query <- paste0("SELECT * FROM sales_tbl WHERE date='", dt, "'")
result <- dbGetQuery(connect, query)
The safest way is to parameterize the query as mentioned here
Example:
library(RPostgreSQL)
dt <- '2018-01-03'
connect <- dbConnect(drv = PostgreSQL(),
dbname ="test",
host = "localhost",
port = 5432,
user = "user",
password = "...")
query <- "SELECT * FROM sales_tbl WHERE date= ?"
sanitized_query <- dbSendQuery(connect, query)
dbBind(sanitized_query, list(dt))
result <- dbFetch(sanitized_query)
Here by passing ? you are sanitizing your query to avoid SQL injection attacks.
Another thing I like to do is to create .Renviron file to store my credintials. For example, for the connection above, the .Renviron file will look like this.
dbname = test
dbuser = me
dbpass = mypass
dbport = 5432
dbhost = localhost
save the file, restart RStudio (to load the .Renviron file at startup). Then access the credentials using the Sys.getenv(variable)
#example:
connect <- dbConnect(drv = PostgreSQL(),
dbname = Sys.getenv("dbname"),
host = Sys.getenv("dbhost"),
port = Sys.getenv("dbport"),
user = Sys.getenv("dbuser"),
password = Sys.getenv("dbpass"))

R ODCB/DBI writing to a SQL Server table with non-default schemas

I've been very excited about the new schema behavior in dbWriteTable but have not been able to get it working. I'm running DBI 0.7-15 and SQL Server 2012. Perhaps I am just using the Id function incorrectly?
The following code block cannot find the correct method.
cs <- "driver={SQL Server};
server={localhost};
database=testSAM;
trusted_connection=true;"
con <- DBI::dbConnect(odbc::odbc(), .connection_string = cs)
df <- data.frame(id=1, word_of_day = "happy")
table_id <- DBI::Id(name = "hcai_unit_tests",
schema = "dbo",
catalog = "testSAM")
# Try with Id
res <- DBI::dbWriteTable(conn = con,
name = table_id,
value = df,
append = TRUE)
# Errors with:
Error in (function (classes, fdef, mtable) :
unable to find an inherited method for function ‘dbWriteTable’ for
signature ‘"Microsoft SQL Server", "SQL", "missing"’
Trying to use dbQuoteIdentifier produces a different error
res <- odbc::dbWriteTable(conn = con,
name = DBI::dbQuoteIdentifier(con, t),
value = df,
append = TRUE)
# Errors with:
Error: <SQL> 'CREATE TABLE "testSAM"."dbo"."hcai_unit_tests" (
"id" FLOAT,
"word_of_day" varchar(255)
)
'
nanodbc/nanodbc.cpp:1587: 42S01: [Microsoft][ODBC SQL Server Driver]
[SQL Server]There is already an object named
'hcai_unit_tests' in the database.
Here, append=TRUE should be preventing this error from coming up...

Insert R data.frame data into HIVE DB

I have a data.frame with 1000-2000 records. I am using RJDBC to insert into HIVE and followed below steps but I am getting an error
library(RJDBC)
drv <- JDBC(driverClass = "org.apache.hive.jdbc.HiveDriver", classPath = list.files("C:/R
Install/hive_lib",pattern="jar$",full.names=T),identifier.quote="'")
conn <- dbConnect(drv, "servername", "username", "pwd")
dbWriteTable(conn, name = tablename, value = data.frame, row.names = FALSE)
Error:
Error in .local(conn, statement, ...) :
execute JDBC update query failed in dbSendUpdate (Error while compiling statement: FAILED: ParseException line 1:334 mismatched input 'PRECISION' expecting ) near 'DOUBLE' in create table statement)
What is the best way to insert R data frame records into HIVE?

Resources