将参数传递给RMySQL dbSendQuery

时间:2015-08-02 16:16:06

标签: r rmysql

我在将值传递给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

我的语法问题是什么?

感谢。

2 个答案:

答案 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