1

Trying to insert R data frame as parameter in SQL query where clause but I get a SQL error.

This is my code:

df <- data.frame(X=c(12691683,12693928)) %>% paste0(collapse = ",")

dbGetQuery(con2,"
  SELECT * FROM ORDERS WHERE ORDER_ID IN (", df, ")
")
1
  • You may want to consider parameterized queries vice constructing query strings manually. In addition to security concerns about malicious SQL injection (e.g., XKCD's Exploits of a Mom aka "Little Bobby Tables"), it is also a concern for malformed strings or Unicode-vs-ANSI mistakes, even if it's one data analyst running the query. DBI supports parameterized queries; RODBC does not (because RODBCext has since been removed). Commented Aug 26, 2022 at 19:38

2 Answers 2

1

With glue::glue_sql(), you could input multiple values for use in SQL IN statements by putting * at the end of the value and the values will be collapsed and quoted appropriately.

df <- data.frame(X = c(12691683, 12693928))

glue::glue_sql(
  "SELECT * FROM ORDERS WHERE ORDER_ID IN ({df$X*})",
)

# <SQL> SELECT * FROM ORDERS WHERE ORDER_ID IN (12691683, 12693928)

In base you could also use sprintf() to create the SQL query:

sprintf("SELECT * FROM ORDERS WHERE ORDER_ID IN (%s)",
        paste(df$X, collapse = ','))

# [1] "SELECT * FROM ORDERS WHERE ORDER_ID IN (12691683,12693928)"
Sign up to request clarification or add additional context in comments.

Comments

1

Use sprintf and toString. No packages are used. We assume this is an internal application where security issues are not relevant.

df <- data.frame(X=c(12691683,12693928))

sql <- sprintf("SELECT * FROM ORDERS WHERE ORDER_ID IN (%s)", toString(df$X))
sql
## [1] "SELECT * FROM ORDERS WHERE ORDER_ID IN (12691683, 12693928)"

A variation of this is to use with

sql <- with(df, 
  sprintf("SELECT * FROM ORDERS WHERE ORDER_ID IN (%s)", toString(X)))

5 Comments

"where security issues are not relevant" should perhaps be bolded :-), but it's not always malicious: typos, unicode, different classes (strings, timestamps) all cause parsing problems when used in this fashion. The use of sQuote or similar is not a robust work-around. The only way to be agnostic to all of this variation is to use bound parameters (dbi.r-dbi.org/reference/dbbind and db.rstudio.com/best-practices/run-queries-safely). It's not much extra work and it saves so much trouble down the road.
It should not be bolded because it is not relevant to 99% of R applications which are just add hoc statistical analyses. I Just pointed it out since you always have somebody claiming it is a problem because of groupthink. The example here does not involve quotes because the values are numeric. If you do have character strings using quotes is not fragile and bringing in extra packages is not simpler and it does not cause problems down the road.
1. No other packages, this is built in to DBI. 2. When somebody comes to this and applies your code to their problem, they may not understand when quotes are and are not needed. I know because there are still frequent questions that use this technique here without quotes (and don't work). 3. I understand that many R users are not deploying code to thousands of consumers, but shiny is easy, and that deployment can easily break on simple things. 4. This isn't groupthink, it's a "best practice" of SQL, even in R. My point though is not to debate, it's to add a comment to your answer.
The example in th e other answer used glue. That is an extra package. The example in the question does NOT need quotes It is completely irrelevant.
I wasn't making a comment about the use of glue_sql, though I find it much safer than paste, sprintf, and toString, if for no other reason than it properly quotes as required by the specific DBMS (not required with numbers, true). The reason I commented here was because of the mention of "security" as the only reason to worry about data binding: while that is the populous reason, it is not the only justification. I respect your work, even if we disagree on the value of the teaching moment here.

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.