【问题标题】:How to use SQL parameters in an R markdown SQL chunk如何在 R markdown SQL 块中使用 SQL 参数
【发布时间】:2021-06-15 06:52:51
【问题描述】:

在 Rmd SQL 代码块中包含参数的正确方法是什么?这是一个示例 Rmd 文件:

---
title: "Rmd Example"
output:
  html_document:
    df_print: paged
  pdf_document: default
---
`r Sys.Date()`
This is an example of an Rmd file.
```{r}
library(tidyverse)
library(DBI)
library(odbc)
library(knitr)
options(connectionObserver = NULL)
con = dbConnect(odbc::odbc(), 
                dsn = "myDsn", 
                uid = "myUsername", 
                pwd = "myPassword")
d1=as.Date("2021-03-15")
```
Look for all encounters after `r d1`
```{sql, connection=con, output.var = "encounters"}
select *
from encounters
where date>?d1
```
There are `r nrow(encounters)` after `r d1` and they are
```{r}
kable(encounters)
```
This ends the document.

SQL 代码块中的?d1 部分不起作用,因为它不是字符串。假装我从其他来源获得d1,它不能硬编码到 SQL 查询本身中。与数据库交互的正常方法是参数化这个值,据我了解,它做了两件非常重要的事情:

  1. 确保参数值具有正确的数据类型,并且
  2. 通过正确转义字符来防止 SQL 注入

R确实有能力支持参数化,例如

library(tidyverse)
library(DBI)
library(odbc)
options(connectionObserver = NULL)
con = dbConnect(odbc::odbc(), 
    dsn = "myDSN",
    uid = "myUsername", 
    pwd = "myPassword")
d1=as.Date("2021-03-15")
query="select * from encounters where date>:d1"
encounters=dbGetQuery(con,query,params=d1)

这个 R 代码运行良好。如何让 R markdown SQL 代码块接受这样的 SQL 参数? ?d1 语法显然只插入文本,它不处理数据类型,虽然文档不清楚,但我怀疑它是否也能正确转义字符。

需要明确的是,我并不是在寻找一种时髦的 hack 来让代码运行。我可以使用直接的 R 代码而不是 SQL 块——失去语法突出显示比失去对参数的正确评估更可取。我正在寻找将 SQL 参数放入 SQL 块中的正确方法。

【问题讨论】:

标签: r oracle r-markdown knitr


【解决方案1】:

也许这是一个适合你的解决方案,使用glue_sql,它可以在我的电脑上运行

https://community.rstudio.com/t/using-multiple-r-variables-in-sql-chunk/2940/13

Rmd 块:

library(DBI)
library(glue)
library(RSQLite)

con <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")
dbWriteTable(con, "mtcars", mtcars, overwrite = TRUE)

cyl_int <- c(4L, 6L)
cyl_sql <- glue_sql("{cyl_int*}")

  SELECT * FROM mtcars
  WHERE cyl IN (?cyl_sql)
  LIMIT 3

对于日期列,您可能必须根据您的数据库正确格式化它或使用to_date(etc, '%d%...') 在 sqlite 中,使用 ISO-8601 日期很容易,例如:

library(DBI)
library(glue)
library(RSQLite)

con <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")
mtcars$DATE_1 <- seq(from = Sys.Date() - 15, to = Sys.Date() + nrow(mtcars) -16, by = 1) %>% as.character()
dbWriteTable(con, "mtcars", mtcars, overwrite = TRUE)

cyl_int <- c(4L, 6L)
cyl_sql <- glue_sql("{cyl_int*}")

d_date_sql <- glue_sql("{Sys.Date()*}", .con = con)

请注意,您必须为字符参数指定 .con 参数,如here 所说

  SELECT cyl, mpg, DATE_1 FROM mtcars
  WHERE DATE_1 >= ?d_date_sql
  ORDER BY DATE_1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-07
    • 1970-01-01
    • 1970-01-01
    • 2010-11-05
    • 1970-01-01
    • 2011-03-25
    • 1970-01-01
    相关资源
    最近更新 更多