R writing a function to extract data from an Oracle database - r

I'm trying to write a function in R, which takes an input and adds it to a pre-defined SQL query. This is to avoid rewriting the same query every time the input changes, and using the function instead.
But I am having problems with the syntax of the function.
The Function
The function takes as input a unique ID, and returns a site name(s).
library(RODBC)
con= odbcConnect(dsn = "DB", uid="morp101", pwd="abcdxyz1234",rows_at_time=500)
getsitename=function(input) {
sitename=sqlQuery(con,"Select DISTINCT(SITE_NAME) FROM SITE_TABLE
WHERE SITE_CODE = '&input&'")
return(sitename)
}
The above function should give the following output when tested
getsitename(1011APQ)
Result: Madison Bay
However the syntax is wrong, not sure how to concatenate the input correctly.
Any advice would be highly appreciated. And apologies for lack of reproducible data, was not sure how I could obtain it for this question.

You can use paste0() to create your query:
getsitename=function(input) {
query = paste0("Select DISTINCT(SITE_NAME) FROM SITE_TABLE WHERE SITE_CODE = '", input, "'")
sitename=sqlQuery(con,query)
return(sitename)
}
So when input='1234', the paste0() statement returns
"Select DISTINCT(SITE_NAME) FROM SITE_TABLE WHERE SITE_CODE = '1234'"

Related

Vectorized Operation in R causing problems with custom function

I'm writing out some functions for Inventory management. I've recently wanted to add a "photo url column" to my spreadsheet by using an API I've used successfully while initially building my inventory. My Spreadsheet header looks like the following:
SKU | NAME | OTHER STUFF
I have a getProductInfo function that returns a list of product info from an API I'm calling.
getProductInfo<- function(barcode) {
#Input UPC
#Output List of product info
CallAPI(barcode)
Process API return, remove garbage
return(info)
}
I made a new function that takes my inventory csv as input, and attempts to add a new column with product photo url.
get_photo_url_from_product_info_output <- function(in_list){
#Input GetProductInfo Output. Returns Photo URL, or nothing if
#it doesn't exist
if(in_list$DisplayStockPhotos == TRUE){
return(in_list$StockPhotoURL)
} else {
return("")
}
}
add_Photo_URL <- function(in_csv){
#Input CSV data frame, appends photourl column
#Requires SKU (UPC) assumes no photourl column
out_csv <- mutate(in_csv, photo =
get_photo_url_from_product_info_output(
getProductInfo(SKU)
)
)
}
return (out_csv)
}
#Call it
new <- add_Photo_URL(old)
My thinking was that R would simply input the SKU of the from the row, and put it through the double function call "as is", and the vectorized DPLYR function mutate would just vectorize it. Unfortunately I was running into all sorts of problems I couldn't understand. Eventually I figured out that API call was crashing because the SKU field was all messed up as it was being passed in. I put in a breakpoint and found out that it wasn't just passing in the SKU, but instead an entire list (I think?) of SKUs. Every Row all at once. Something like this:
#Variable 'barcode' inside getProductInfo function contains:
[1] 7.869368e+11 1.438175e+10 1.256983e+10 2.454357e+10 3.139814e+10 1.256983e+10 1.313260e+10 4.339643e+10 2.454328e+10
[10] 1.313243e+10 6.839046e+11 2.454367e+10 2.454363e+10 2.454367e+10 2.454348e+10 8.418870e+11 2.519211e+10 2.454375e+10
[19] 2.454381e+10 2.454381e+10 2.454383e+10 2.454384e+10 7.869368e+11 2.454370e+10 2.454390e+10 1.913290e+11 2.454397e+10
[28] 2.454399e+10 2.519202e+10 2.519205e+10 7.742121e+11 8.839291e+11 8.539116e+10 2.519211e+10 2.519211e+10 2.519211e+10
Obviously my initial getProductInfo function can't handle that, so it'll crash.
How should I modify my code, whether it be in the input or API call to avoid this vectorized operation issue?
Well, it's not totally elegant but it works.
I figured out I need to use lapply, which is usually not my strong suit. Initally I tried to nest them like so:
lapply(SKU, get_photo_url_from_product_info_output(getProductInfo())
But that didn't work. So I just came up with bright idea of making another function
get_photo_url_from_sku <- function(barcode){
return(get_photo_url_from_product_info_output(getProductInfo(barcode)))
}
Call that in the lapply:
out_csv<- mutate(in_csv, photocolumn = lapply(SKU, get_photo_url_from_sku))
And it works great. My speed is only limited by my API calls.

RODBC channel error in global environnement

I've set up a connection between R and SQL using the package RODBC and managed to connect and query the database from R.
I've created a small R function which objective is to delete some lines (as parameter) in a specific table.
Here it is (nameDB is the name of my database, and values_conversion another function I did to convert some data from R format to SQL format) :
delete_SQL = function(data, table){
ch = odbcConnect(nameDB,"postgres")
names = sqlColumns(channel=ch,table,schema="public",catalog = nameDB)$COLUMN_NAME
for(i in 1:nrow(data)){
sqlQuery(channel=ch,query=paste0("DELETE FROM public.\"",table,"\" WHERE ",
paste0(names," = ",values_conversion(data[i,]),collapse = " and "),";"),errors = TRUE)
}
odbcCloseAll()
}
Query exemple : "DELETE FROM public.\"lieu_protection\" WHERE lieu_id = 3 and protection_id = 1430;"
The code inside this function works fine when I execute everything directly, but when I call the function it throws an
Error in sqlQuery(channel = ch, query = paste0("DELETE FROM public.\"", :
first argument is not an open RODBC channel
I have a similar function that's getting and returning data from SQL and which is working fine, so I guess it has something to do with the delete, but the error is about the channel, so I'm quite confused.
Thanks to anyone that can help !

mongolite filtering with dynamic array in r shiny

I have a select input with multiple options and my Mongo query
Here is the array if elements:
c<- c("elen","shallen")
query1 <- paste0('{"client": {"$in"["',c,'"]}')
#sales info is the data base
salesinfo$find(fields = '{"store":true,"_id":false}',query = query1)
Error: Invalid JSON object: {"client": [ elen ]}{"client": [ shallen ]}
this isn't working please help me please remember that it is a dynamic array and the values will change
After extensive research i found a way to solve the issue and i hope my solution will help out guys like me.
q1=paste(shQuote(c, type="cmd"), collapse=", ")
this step is to ensure you print out the array as a string and then use the query
query =paste0('{"store":{"$in":[',q1,']}}')
and the next step would be incorporating it to the query
salesinfo$find(fields = '{"store":true,"_id":false}',query = query)

unable to run sql query against oracle table in R

I can run this query in sqlplus against an oracle table, it works I get results back:
SELECT * FROM KEYNOTE_PRD WHERE KEYNOTE_PRD."Site"='High Frequency NY Traffic'
but I try to same with the following code within R:
tryCatch({
ch=odbcConnect("<id>",pwd = "<passwd>")
sql<-c("SELECT * FROM KEYNOTE_PRD WHERE KEYNOTE_PRD."Site"='High Frequency NY Traffic'")
res<-sqlQuery(ch, sql)
},error = function(e) {
print(odbcGetErrMsg(ch))
print("retrive or connect to the db")
})
odbcClose(ch)
It does not work. I think it does not like the double quotes within double quotes (KEYNOTE_PRD."Site"). Any ideas how would I get around this?
This will help someone who is not familiar with the Oracle. The asnwer was very simple.
I changed the column names to capital letters and this problem resolved. This must be an oracle thing.
tryCatch({
ch=odbcConnect("<id>",pwd = "<passwd>")
sql<-c("SELECT * FROM KEYNOTE_PRD WHERE KEYNOTE_PRD.SITE='High Frequency NY Traffic'")
res<-sqlQuery(ch, sql)
},error = function(e) {
print(odbcGetErrMsg(ch))
print("retrive or connect to the db")
})
odbcClose(ch)
I just ran into the same type of issue where the column names were lower and I had no control over the tables. The solution was to escape the quotes with single \ character. It worked like a charm.

db operation exception handling in R

I am using the following function to select values from a table.Table name is given as the parameter to that function.If the table does not exist an error generated and the execution is stoped.I want to do something if the table is not found.Is it possible in R? something like try-catch exception ?
library('RSQLite')
getData <- function(portfolio){
lite <- dbDriver("SQLite", max.con = 25)
db <- dbConnect(lite, dbname = "portfolioInfo.db")
res <- dbSendQuery(db, paste("SELECT * from ",portfolio," ",sep=""))
data <- fetch(res)
return (data)
}
getData("table1")
One way to do this would be to check the class of the data that is returned.
I am not familiar with RSQLite but I guess it will return a dataframe if the table is found and a text error when not?
So a possibility would be to check whether or not an error is raised:
checkQueryResult<-function(data){
if(class(data)=='data.frame') cat('SQL execution worked!')
else cat('Something went wrong, table does not exist?')
}
checkQueryResult(getData("table1"))
But maybe the RSQLite package already has error handling stuff built in?

Resources