我在将值传递给dbSendQuery时遇到了困难。 以下是我的代码:
参数:
date_param <- '2014_02_02'
查询:
pull <- dbSendQuery(test_db, "select distinct product_id, group
from test_table
where date between date_sub(",date_param,", interval 1 year) and ",date_param," ;")
pulled_data <- fetch(pull, n=-1)
我得到的错误是:
Error in is(object, Cl) :
internal error in RS_DBI_getResultSet: could not find resultSet in connection
我的语法问题是什么?
感谢。
答案 0 :(得分:3)
您需要将SQL语句合并为一个字符串。现在,您将作为单独的参数传递。尝试使用fallback_fonts.xml
进行陈述。
paste()
答案 1 :(得分:1)
我知道这是一个非常古老的问题,所以我希望你已经解决了你的问题。正如@MrFlick建议的那样,paste
构建一个字符串并允许您将其作为单个参数传递。但是,在这样做时,您必须执行一些语义来确保正确引用日期。由于我没有您正在讨论的表(或有关其中的数据的信息),我将构建一个简单的查询来显示正在发生的事情。
目前,您可能提交给数据库的内容类似于:
date_param <- "2014_02_02"
## currently submitting
paste0("select distinct product_id, group from test_table where date between date_sub(",
date_param, ", interval 1 year) and ", date_param, " ;")
#> [1] "select distinct product_id, group from test_table where date between date_sub(2014_02_02, interval 1 year) and 2014_02_02 ;"
## analogous query
paste0("select date_sub(", date_param, ", interval 1 year) as start , ", date_param,
" as end;")
#> [1] "select date_sub(2014_02_02, interval 1 year) as start , 2014_02_02 as end;"
## need to quote the dates
paste0("select date_sub('", date_param, "', interval 1 year) as start , '",
date_param, "' as end;")
#> [1] "select date_sub('2014_02_02', interval 1 year) as start , '2014_02_02' as end;"
如果您将最后一个查询复制并粘贴到SQL编辑器中,它应该按照您期望的方式工作(注意日期周围的引号)。
使用paste
(或paste0
- 无分隔符)的好处是,您可以准确捕获正在发送的查询,并在SQL编辑器中自行测试。缺点是令人恼火的引用行为和SQL注入风险(以及缺乏类型安全性)。 更好的解决方案是使用变量替换,它根据实现有所不同(RMySQL和RMariaDB使用?
,RPostgreSQL和RPostgres使用$1
,$2
$3
,等)。有关详细信息,请参阅DBI Spec
- 您有时也可以通过提前准备查询来获得性能提升。
另请注意,RMySQL
包正在逐步淘汰 - RMariaDB
与MySQL和MariaDB兼容,并且正在进行未来的开发。 (根据我的探索,看起来RMySQL
包对这样的准备查询没有很好的支持)
library(RMariaDB)
date_param <- "2014_02_02"
conn <- dbConnect(MariaDB(), ...)
query <- "select date_sub(?, interval 1 year) as start, date(?) as end;"
rs <- dbSendQuery(conn, query, list(date_param, date_param))
dbFetch(rs)
#> start end
#> 1 2013-02-02 2014-02-02
dbClearResult(rs)
#> [1] TRUE