R使用dbBind将参数传递给SQL IN子句(可能没有胶水包?)
只是想知道是否可以使用DBI将参数传递给SQL查询IN子句?已尝试以下操作(以及许多变体,包括未命名的参数)R使用dbBind将参数传递给SQL IN子句(可能没有胶水包?),r,rstudio,r-dbi,R,Rstudio,R Dbi,只是想知道是否可以使用DBI将参数传递给SQL查询IN子句?已尝试以下操作(以及许多变体,包括未命名的参数) con列表中的两个元素必须具有相同的长度。从?dbBind中的值部分: 绑定太多或太少的值,或参数名称错误或长度不等,也会引发错误。如果查询中的占位符已命名,则所有参数值必须具有名称(不能为空或NA),反之亦然,否则将引发错误 在《规范》dbBind中进一步说明: 此列表中的所有元素必须具有相同的长度,并且包含后端支持的值 以下内容适合我: library(RSQLite) con &l
con列表中的两个元素必须具有相同的长度。从?dbBind
中的值部分:
绑定太多或太少的值,或参数名称错误或长度不等,也会引发错误。如果查询中的占位符已命名,则所有参数值必须具有名称(不能为空或NA),反之亦然,否则将引发错误
在《规范》dbBind中进一步说明:
此列表中的所有元素必须具有相同的长度,并且包含后端支持的值
以下内容适合我:
library(RSQLite)
con <- dbConnect(RSQLite::SQLite(), ":memory:")
dbWriteTable(con, "iris", iris)
iris_result <- dbSendQuery(con, "SELECT * FROM iris WHERE [Petal.Length] = $PL and [Petal.Width] > $PW")
pl <- c(6.0, 5.1)
dbBind(iris_result, list(PL=pl, PW=rep(2.3, length(pl))))
dbFetch(iris_result)
库(RSQLite)
con如果您想使用dbBind()
在SQL的子句中绑定一个未定义数量的实际值:您不能强>
library(RSQLite)
con <- dbConnect(RSQLite::SQLite(), ":memory:")
dbWriteTable(con, "iris", iris)
iris_result <- dbSendQuery(con, "SELECT * FROM iris WHERE [Petal.Width] > $PW and [Petal.Length] in ($PL)")
dbBind(iris_result, list(PW=2.3, PL=list(6.0, 5.1)))
# Error in rsqlite_bind_rows(res@ptr, params) : Parameter 2 does not have length 1.
选项2(如果
元素中的数量发生变化):
您还可以计算实际参数的数量,并在
子句中的中生成相同数量的查询参数,然后使用dbSendQuery
准备SQL查询。这将防止SQL代码注入:
in.params <- c(PL1=6.0, PL2=5.1, PL3=5.6)
sql <- paste0("SELECT * FROM iris WHERE [Petal.Width] > $PW and [Petal.Length] in (",
paste0("$", names(in.params), collapse = ", "),
")")
iris_result <- dbSendQuery(con, sql)
dbBind(iris_result, c(list(PW=2.3), in.params))
dbFetch(iris_result)
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1 6.3 3.3 6.0 2.5 virginica
# 2 5.8 2.8 5.1 2.4 virginica
# 3 6.3 3.4 5.6 2.4 virginica
# 4 6.7 3.1 5.6 2.4 virginica
gsubfn包中的in.paramsfn$
在任何命令之前对其参数执行替换。这不是sql特有的,尽管sqldf确实使用该工具<代码>库(gsubfn);PW我猜在使用参数化查询时,使用原生的DBI
(它是RSQLite
的基础)是不可能的,因为in
子句中的参数通常不能在SQL中参数化,但需要字符串连接来构建SQL查询字符串(打开各种SQL代码注入!)由于最初的帖子可能不清楚,我想补充一点,我的帖子的目的是确定是否可以使用原生DBI,并且我没有语法错误。否则,我并不反对使用胶水包装。仍然要检查下面的答案/其他评论(目前不在R前面),但是,@R Yoda,这回答了我的问题。
library(RSQLite)
con <- dbConnect(RSQLite::SQLite(), ":memory:")
dbWriteTable(con, "iris", iris)
iris_result <- dbSendQuery(con, "SELECT * FROM iris WHERE [Petal.Width] > $PW and [Petal.Length] in ($PL)")
dbBind(iris_result, list(PW=2.3, PL=list(6.0, 5.1)))
# Error in rsqlite_bind_rows(res@ptr, params) : Parameter 2 does not have length 1.
con <- dbConnect(RSQLite::SQLite(), ":memory:")
dbWriteTable(con, "iris", iris)
# Works only if you know the number of IN-elements in adavance...
iris_result <- dbSendQuery(con, "SELECT * FROM iris WHERE [Petal.Width] > $PW and [Petal.Length] in ($PL1, $PL2)")
dbBind(iris_result, list(PW=2.3, PL1=6.0, PL2=5.1))
dbFetch(iris_result)
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1 6.3 3.3 6.0 2.5 virginica
# 2 5.8 2.8 5.1 2.4 virginica
in.params <- c(PL1=6.0, PL2=5.1, PL3=5.6)
sql <- paste0("SELECT * FROM iris WHERE [Petal.Width] > $PW and [Petal.Length] in (",
paste0("$", names(in.params), collapse = ", "),
")")
iris_result <- dbSendQuery(con, sql)
dbBind(iris_result, c(list(PW=2.3), in.params))
dbFetch(iris_result)
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1 6.3 3.3 6.0 2.5 virginica
# 2 5.8 2.8 5.1 2.4 virginica
# 3 6.3 3.4 5.6 2.4 virginica
# 4 6.7 3.1 5.6 2.4 virginica