使用 R 的 `DBI` 直接在数据库中获取参数化查询 `rbind`ed *and* 的结果集

问题描述 投票:0回答:2

使用 R 的

DBI
,我需要:

  1. 使用不同的参数(即参数向量)运行参数化查询;
  2. 获得连接的结果集(即
    rbind
    ed按照R术语或
    union
    ed按照SQL术语);
  3. 并在数据库中获取结果表以供进一步操作。

dbBind
/
dbGetquery
满足要求 1 和 2,但我需要使用
dbWriteTable
将生成的数据框写入数据库,这是低效的:

library(DBI)
con <- dbConnect(RSQLite::SQLite(), ":memory:")
dbWriteTable(con, "iris", iris)

res <- dbGetQuery(con,
                  "select * from iris where Species = ?",
                  params = list(c("setosa", "versicolor")))

dbWriteTable(con, "mytable", res)

相反,

dbExecute
满足需求3,但我认为它没有“
rbind
特征”。当然,这会引发错误,因为表格会被覆盖:

dbExecute(con,
          "create table mytable as select * from iris where Species = ?",
          params = list(c("setosa", "versicolor")))

最有效/推荐的方法是什么?

备注:

  • 我不是DBA,只能通过R访问数据库
  • 我的示例太简单了,可以在单个查询中实现。我的用例确实需要使用不同参数多次运行参数化查询。
  • 我必须使用 Oracle,但我对解决方案感兴趣,即使它不适用于 Oracle。
sql r dbi r-dbi
2个回答
1
投票

1) 使用第一个参数创建表,然后将其他每个参数插入其中。

library(RSQLite)

con <- dbConnect(SQLite())
dbWriteTable(con, "iris", iris)

parms <- c("setosa", "versicolor")

dbExecute(con, "create table mytable as
  select * from iris where Species = ?",
  params = parms[1])
for (p in parms[-1]) {
  dbExecute(con, "insert into mytable
    select * from iris where Species = ?",
    params = p)
}

# check
res <- dbGetQuery(con, "select * from mytable")
str(res)

2) 交替生成 SQL 语句的文本来完成这一切。 sqldf 引入 RSQLite 和 gsubfn,后者提供启用文本替换的 fn$。

library(sqldf)

con <- dbConnect(SQLite())
dbWriteTable(con, "iris", iris)

parms <- c("setosa", "versicolor")
parmString <- toString(sprintf("'%s'", parms))
fn$dbExecute(con, "create table mytable as
  select * from iris where Species in ($parmString)")

# check
res <- dbGetQuery(con, "select * from mytable")
str(res)

3) (2)的变体是插入适当数量的问号。

library(sqldf)

con <- dbConnect(SQLite())
dbWriteTable(con, "iris", iris)

params <- list("setosa", "versicolor")
quesString <- toString(rep("?", length(params)))

fn$dbExecute(con, "create table mytable as
  select * from iris where Species in ($quesString)", params = params)

# check
res <- dbGetQuery(con, "select * from mytable")
str(res)

0
投票

基于@r2evans 的评论和@G.Grothendieck 的回答,我使用了直接插入表中的参数化查询,而不是查询/下载/组合/上传。

首先,我创建了包含适当列的表来收集结果:

library(DBI)
con <- dbConnect(RSQLite::SQLite(), ":memory:")

create_table <-
"
CREATE TABLE
  warpbreaks2 (
    breaks real,
    wool text,
    tension text
);
"

dbExecute(con, create_table)

然后我执行了一个

INSERT INTO
步骤:

dbWriteTable(con, "warpbreaks", warpbreaks)

insert_into <-
"
INSERT INTO
  warpbreaks2
SELECT
  warpbreaks.breaks,
  warpbreaks.wool,
  warpbreaks.tension
FROM
  warpbreaks
WHERE
  tension = ?;
"

dbExecute(con, insert_into, params = list(c("L", "M")))

这是一个用于说明目的的虚拟示例。它可以通过例如更直接地实现:

direct_query <-
"
CREATE TABLE
  warpbreaks3 AS
SELECT
  *
FROM
  warpbreaks
WHERE
  tension IN ('L', 'M');
"

dbExecute(con, direct_query )
© www.soinside.com 2019 - 2024. All rights reserved.