问题
I have a rather simple question.
On a daily basis, I perform data analysis in R using the RODBC package. I connect it to our data warehouse using SQL and move it into the R environment
dbhandle <- odbcDriverConnect('driver={SQL Server};server=SQLSERVER;database=MYDATABASE;trusted_connection=true')
degrees <- sqlQuery(dbhandle, "select Inst, ID, DegreeDate, Degree from DEGREE where FY = ('2015') group by Inst, ID, DegreeDate, Degree order by Inst, ID, DegreeDate, Degree", as.is=TRUE)
You know how in MS Access, you can have a window pop up that asks you what FY for example? You put in 2015 and you'll get all the degress from that fiscal year.
Is there any way to do it in R? The parameter query questions I see on Stack Overflow deal with changing the data in the SQL database and I'm not interested in that. I just want to set some pretty basic limits so I can rerun code.
Some may wonder "why can't you just change the 5 to a 6?" That's a fair point but I'm concerned that, with more complicated queries, users may miss a part in the SQL query to change the 5 to a 6 and that would mess the analysis up or slow it down.
Thank you! Walker
回答1:
You can create a input variable at the start and pass it to your query. For example:
# Change your FY here
input_FY <- 2016
dbhandle <- odbcDriverConnect('driver={SQL Server};server=SQLSERVER;database=MYDATABASE;trusted_connection=true')
degrees <- sqlQuery(dbhandle, paste0("
select Inst, ID, DegreeDate, Degree
from DEGREE
where FY = ('", input_FY, "')
group by Inst, ID, DegreeDate, Degree
order by Inst, ID, DegreeDate, Degree"),
as.is=TRUE)
So for any complicated queries you can still pass the same input_FY
variable or any other variable that you have declared at the start of code for a quick/easy update.
回答2:
The Input Parameter pop-up box is strictly an MSAccess.exe GUI feature. If running MS Access as a backend database (outside of the MS Office software) via ODBC, query with unknown parameter will fail and error raised on the script making ODBC call.
Therefore, you will need to create a similar GUI pop-up box in R for this need using libraries such as GWidgets or Shiny, then pass user's input value into query. And do so with actual parameterization using RODBCext (extension of RODBC) in case a malicious user runs SQL injection and potentially wipes data or destroys your SQL Server database.
Below is an example using GWidgets2 with a combo box for Fiscal Years (screenshot below).
Libraries
library(RDOBC)
library(RODBCext)
library(gWidgets2)
library(gWidgets2tcltk)
options(guiToolkit="tcltk")
GUI Function (create the R and SQLServer gif image beforehand)
mainWindow <- function(){
# TOP OF WINDOW
win <- gWidgets2::gwindow("Fiscal Year User Input", height = 200, width = 300)
tbl <- glayout(cont=win, spacing = 8, expand=TRUE)
# IMAGE
tbl[1,1] <- gimage(filename = "RSQLServerGUI.gif",
dirname = "/path/to/gif/image", container = tbl)
# LABEL
tbl[2,1] <- glabel("Fiscal Year Selection: ", container = tbl)
font(tbl[2,1]) <- list(size=12, family="Arial")
# COMBO BOX OF FISCAL YEARS
tbl[3,1, expand=TRUE] <- fiscal_year_cbo <- gcombobox(as.character(c(2012:2018)),
selected = 1, editable = TRUE,
index=TRUE, container = tbl)
font(tbl[3,1]) <- list(size=16, family="Arial")
# COMBO BOX CHANGE FUNCTION (2012 - 2018)
addHandlerChanged(fiscal_year_cbo, handler=function(...) {
fiscal_year_value <- svalue(fiscal_year_cbo) # GET USER SELECTED VALUE
gmessage(paste("You selected FY:", fiscal_year_value))
degrees <- getDegreesData(fiscal_year_value) # GET DATABASE DATA
dispose(win) # CLOSE WINDOW
})
}
Query Function (called in combo box change handler above)
getDegreesData <- function(fy_param) {
dbhandle <- odbcDriverConnect('driver={SQL Server};server=SQLSERVER;database=MYDATABASE;trusted_connection=true')
# PREPARED STATEMENT (NO CONCATENATED DATA)
strSQL <- "select Inst, ID, DegreeDate, Degree
from DEGREE
where FY = ?
group by Inst, ID, DegreeDate, Degree
order by Inst, ID, DegreeDate, Degree"
# PASS PARAMETER TO RETURN DATAFRAME
sql_df <- sqlExecute(dbhandle, strSQL, fy_param, fetch=TRUE)
odbcClose(dbHandle)
return(sql_df)
}
Run GUI
m <- mainWindow()
Screenshot
来源:https://stackoverflow.com/questions/50760450/parameterize-sql-queries-using-r-rodbc