1

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
  • If RODBC doesn't already support this, then my guess is that you might have to implement some or all of this yourself. Commented Jun 8, 2018 at 12:27

2 Answers 2

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

GUI Output

Sign up to request clarification or add additional context in comments.

Comments

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.

4 Comments

Thank you! But I didn't get a dataframe from this did i do something wrong? It turned into a character
What does degrees return? It should return a dataframe, I am thinking it returned a character either because the channel dbhandle is not open or the table DEGREE does not exist.
My sincere apologies. I fixed it and it worked. I was using more basic variable names on stackoverflow and forgot to change them. dooh! thank you, @MKa!
Do note: there is no parameterization in this answer only string concatenation which if you allow user to enter the value, beware of sql injection: Bobby Tables!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.