Parameterize SQL Queries using R RODBC

≯℡__Kan透↙ 提交于 2019-12-23 02:43:07

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!