Connecting to SQL Server on shinyapps.io

  • January 31, 2018
  • steph
  • R

If you use SQL Server (or Azure SQL DB) as your data store and you need to connect to the databasse from shinyapps.io, you’re presently stuck with FreeTDS. If you have any control over infrastructure I cannot recommend highly enough the actual ODBC Driver on Linux for ease. Alas, shinyapps.io does not let you control the infrastructure. We have to make do with with FreeTDS and it can be pretty painful to get right.

Due to how obtuse the error messages you end up getting back from FreeTDS in your shiny app and the time to deploy an app, you might just want to cry a little. I know I did. Determined to succeed, here is my solution to getting a working database connection that you can also use to test you’re doing it right. If you’re on a particularly old version of SQL Server though, I can’t guarantee this will work for you.

library(DBI)
library(odbc)

server = "lockedata.westeurope.cloudapp.azure.com"
database = "datasci"
uid = "example"
pwd = "HBBFSE"

dbConnect(
  odbc(),
  Driver      = "FreeTDS",
  Database    = database,
  Uid         = uid,
  Pwd         = pwd,
  Server      = server,
  Port        = 1433,
  TDS_Version = 7.4
)

I then had some downstream problems with dbReadTable() where it yielded incorrect syntax error messages. As I was strapped for time so I simply moved over to using dbGetQuery() and writing a SELECT statement instead.

Making it work anywhere

You’re hopefully going to be using the ODBC driver where possible so you need to make your shiny application context aware so your code will run using the ODBC driver locally or FreeTDS when deployed on shinyapps. Here is a check flag and new function that you can use to seamlessly switch you app between database drivers based on whether it’s running on a shiny server.

is_local = Sys.getenv('SHINY_PORT') == ""

server = "lockedata.westeurope.cloudapp.azure.com"
database = "datasci"
uid = "example"
pwd = "HBBFSE"

dbConnector <- function(server, database, uid, pwd, 
               local=TRUE, port=1433, tds_version=7.4){
  if(local){
    DBI::dbConnect(odbc::odbc(), 
      driver = "ODBC Driver 13 for SQL Server",
      server = server, 
	  database = database, 
      uid = uid, 
	  pwd = pwd
	)
    
  }else{
    DBI::dbConnect(odbc::odbc(),
      Driver   = "FreeTDS",
      Database = database,
      Uid      = uid,
      Pwd      = pwd,
      Server   = server,
      Port     = port,
      TDS_Version=tds_version
    )
  }
  }

dbConn <- dbConnector(server, database, uid, pwd, is_local)
Search