Reputation: 1619
I would like to query an ODBC database within Shiny. All I need is for the user to be able to type in someone's ID number, for example, and then to print out the entire row in the table, which is located in the database. What I have so far allows for inputs, but does not seem to be querying the database and printing that information.
This is what I have:
library(RSQLite)
library(RODBC)
library(RODBCext)
library(sqldf)
#connect to database
dbhandle = odbcDriverConnect(...)
library(shiny)
ui <- shinyUI(
pageWithSidebar(
headerPanel("Hide Side Bar example"),
sidebarPanel(
textInput("Id", "Enter Account Number below"),
submitButton(text="Submit")
),
mainPanel(
tabsetPanel(
tabPanel("Data", tableOutput("tbTable"))
)
)
)
)
server <- function(input, output) {
myData <- reactive({
#build query
query = paste0("SELECT Fullname FROM Table WHERE ID= ", input$Id)
#store results
res <- sqlQuery(conn = dbhandle, query = query)
#close database
databaseClose(dbhandle)
#return results
res
})
}
shinyApp(ui = ui, server = server)
Any help is greatly appreciated! Thank you very much.
Upvotes: 2
Views: 4317
Reputation: 17279
There are a handful of changes you'll need to make before this works. Some of the key concepts that need to be pointed out:
output$tbTable
object. This means that your myData
reactive is never being called, so you're never querying your database.RODBC
database connection, and then using DBI
style arguments in sqlQuery
. You should use either DBI
(via RSQLServer
, perhaps--I've never used it) or RODBC
(I use this a lot).dbhandle
after the first time you call it. Is this the intended behavior? That the user should only get one chance at hitting the database?Some minor notes:
RODBCext
so that you can use parameterized queries.Table
is a reserved word in SQL. I'm not sure if this is a placeholder or not, but it can be helpful to wrap your table components in brackets, such as [schema].[table_name].[column_name]My recommendation for your code would be:
library(RODBCext) # Also loads RODBC
library(shiny)
ui <- shinyUI(
pageWithSidebar(
headerPanel("Hide Side Bar example"),
sidebarPanel(
textInput("Id", "Enter Account Number below"),
submitButton(text="Submit")
),
mainPanel(
tabsetPanel(
tabPanel("Data", tableOutput("tbTable"))
)
)
)
)
server <- function(input, output, session) {
myData <- reactive({
req(input$Id)
#connect to database
dbhandle = odbcDriverConnect(...)
#build query
query = "SELECT [Fullname] FROM [schema].[table_name] WHERE [ID] = ?"
#store results
res <- sqlExecute(channel = dbhandle,
query = query,
data = list(input$Id),
fetch = TRUE,
stringsAsFactors = FALSE)
#close the connection
odbcClose(dbhandle)
#return results
res
})
output$tbTable <-
renderTable(
myData()
)
}
shinyApp(ui = ui, server = server)
I seem to recall there is a way to close the database connection when the session closes, but I can't get it to work the way I expected with session$onSessionEnded(odbcClose(dbhandle))
, so someone else may be able to fill in the gap there.
If you don't want to create a new connection everytime you click the button, you can create the connection outside of the reactive, and just not close it. This will leave a hanging connection, though, which I'm not fond of doing.
Upvotes: 4
Reputation: 19544
A reactive
is a function : as long as you don't call it, it's not evaluated.
To fill in the table with the result of the query, you just have to add this code to your server function after the closing parenthesis of the reactive
:
output$tbTable<- renderTable(mydata())
Upvotes: 0