【问题标题】:RPostgreSQL - Passing Parameter in R to a Query in RPostgreSQLRPostgreSQL - 将 R 中的参数传递给 RPostgreSQL 中的查询
【发布时间】:2023-03-29 21:54:02
【问题描述】:

问题:如何在 RPostgreSQL 查询中传递变量?

示例:在下面的示例中,我尝试将日期“2018-01-03”传递给查询

library(RPostgreSQL)

dt <- '2018-01-03'

connect <- dbConnect(PostgreSQL(), 
                 dbname="test",
                 host="localhost",
                 port=5432,
                 user="user", 
                 password="...")
result <- dbGetQuery(connect,
                "SELECT * FROM sales_tbl WHERE date = @{dt}")

【问题讨论】:

标签: r parameter-passing rpostgresql


【解决方案1】:

您可以使用paste0 生成您的查询并将其传递给 dbGetQuery:

library(RPostgreSQL)

dt <- '2018-01-03'

connect <- dbConnect(PostgreSQL(), 
  dbname="test",
  host="localhost",
  port=5432,
  user="user", 
  password="...")

query <- paste0("SELECT * FROM sales_tbl WHERE date='", dt, "'")
result <- dbGetQuery(connect, query)

【讨论】:

  • 当“dt”是日期或值的列表时,您知道如何处理吗?例如'2018-01-03'、'2017-01-03' 等等。
  • 试试这个:dt 然后 paste( "SELECT * FROM sales_tbl WHERE date =", paste0("'", dt, "'", collapse = " OR date = "))
  • 这很容易受到 SQL 注入的攻击。一种改进是使用dbQuoteString()sqlInterpolate() 函数see RStudio Best Practices。据我所知,没有办法用dbGetQuery(con, sql, params)调用的dbBind函数来做到这一点,至少对于DBI的RPostgreSQL实现。
  • @ichbinallen:如果您仍然希望使用dbBind 清理 sql,请阅读下面的答案。没想到我之前没有回复您评论的第二部分。
【解决方案2】:

最安全的方法是参数化查询,如here所述

例子:

library(RPostgreSQL)

dt <- '2018-01-03'

connect <- dbConnect(drv = PostgreSQL(), 
  dbname ="test",
  host = "localhost",
  port = 5432,
  user = "user", 
  password = "...")

query <- "SELECT * FROM sales_tbl WHERE date= ?"
sanitized_query <- dbSendQuery(connect, query)
dbBind(sanitized_query, list(dt))
result <- dbFetch(sanitized_query)

在这里通过?,您正在清理您的查询以避免 SQL 注入攻击。

我喜欢做的另一件事是创建.Renviron 文件来存储我的凭据。例如,对于上面的连接,.Renviron 文件将如下所示。

dbname = test
dbuser = me
dbpass = mypass
dbport = 5432
dbhost = localhost

保存文件,重启RStudio(在启动时加载.Renviron文件)。然后使用Sys.getenv(variable) 访问凭据

#example:
connect <- dbConnect(drv = PostgreSQL(), 
  dbname = Sys.getenv("dbname"),
  host = Sys.getenv("dbhost"),
  port = Sys.getenv("dbport"),
  user = Sys.getenv("dbuser"), 
  password = Sys.getenv("dbpass"))

【讨论】:

  • 如果你有开始日期和结束日期怎么办?那么查询如何变化?
  • 你有没有亲自尝试过,它有效吗?
  • @kRazzyR 是的。您需要更改 SQL 查询。喜欢SELECT * from table WHERE date between "?" and "?"。然后发送那些“?”的参数第二个参数上的占位符,如dbBind(query, list(date1, date2)。让我知道这是否对您有用。
猜你喜欢
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-23
  • 1970-01-01
  • 1970-01-01
  • 2017-05-19
相关资源
最近更新 更多