R 中的 `create table <tabX> as select * from <tabY>` 等语句的 DBI 功能是什么?

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

我正在使用

DBI
/
ROracle
.

conn <- dbConnect(ROracle::Oracle(), ...)

我需要从另一个表中的选择查询创建一个表(即像

create table <tabX> as select * from <tabY>
这样的语句)。

似乎有几个函数可以执行此任务,例如:

dbSendQuery(conn, "create table tab1 as select * from bigtable")
# Statement:            create table tab1 as select * from bigtable 
# Rows affected:        28196 
# Row count:            0 
# Select statement:     FALSE 
# Statement completed:  TRUE 
# OCI prefetch:         FALSE 
# Bulk read:            1000 
# Bulk write:           1000 

或:

dbExecute(conn, "create table tab2 as select * from bigtable")
# [1] 28196

甚至:

tab3 <- dbGetQuery(conn, "select * from bigtable")
dbWriteTable(conn = conn, "TAB3", tab3)
# [1] TRUE

每种方法似乎都有效,但我想在性能/最佳实践方面存在差异。运行像

create table <tabX> as select * from <tabY>
这样的语句的最佳/最有效方法是什么?

我没有在 DBI 和 ROracle 帮助页面中找到任何提示。

r oracle dbi r-dbi roracle
1个回答
1
投票

预先:为此使用

dbExecute
;不要使用
dbSendQuery
,该函数建议返回数据的期望(尽管仍然有效)。

dbSendQuery
只应在您期望返回数据时使用;即使您使用不当,大多数连接也能正常工作,但这就是它的设计。相反,使用
dbSendStatement
/
dbClearResult
或更好但只是
dbExecute
.

以下是一对完全等价的路径:

  • 检索数据:
    • dat <- dbGetQuery(con, qry)
    • res <- dbSendQuery(con, qry); dat <- dbFetch(res); dbClearResult(res)
  • 发送语句(不返回数据,例如
    UPDATE
    INSERT
    ):
    • dbExecute(con, stmt)
    • res <- dbSendStatement(con, stmt); dbClearResult(res)
    • (马虎)
      res <- dbSendQuery(con, stmt); dbClearResult(res)
      (我认为有些数据库抱怨这种方法)

如果您选择

dbSend*
,那么在完成语句/获取后,应该always调用
dbClearResult
。 (R 通常会在你之后清理,但如果这里出现问题——我在过去几年中遇到过几次——连接会锁定,你必须重新创建它。这可能会在数据库中留下孤立连接也一样。)

我认为大多数用例都是单次查询和输出,这意味着

dbGetQuery
dbExecute
是最容易使用的。但是,有时您可能想要重复查询。来自
?dbSendQuery
的例子:

     # Pass multiple sets of values with dbBind():
     rs <- dbSendQuery(con, "SELECT * FROM mtcars WHERE cyl = ?")
     dbBind(rs, list(6L))
     dbFetch(rs)
     dbBind(rs, list(8L))
     dbFetch(rs)
     dbClearResult(rs)

(我认为在没有捕获数据的情况下对

dbFetch
的文档有点草率......我希望
dat <- dbFetch(..)
,在这里丢弃返回值似乎适得其反。)

执行此多步骤(需要

dbClearResult
)的一个优点是可以处理更复杂的查询:数据库服务器通常倾向于根据其执行引擎“编译”或优化查询。对于服务器来说,这并不总是一个非常昂贵的步骤来执行,而且它可以为数据检索带来巨大的好处。服务器经常缓存这个优化的查询,当它看到相同的查询时,它使用查询的已经优化的版本。这是使用参数绑定真正有用的一种情况,因为查询在重复使用中是相同的,因此永远不需要重新优化。

仅供参考,参数绑定可以如上所示使用

dbBind
重复完成,也可以使用
dbGetQuery
使用
params=
参数来完成。例如,这组等效的表达式将返回与上面相同的结果:

qry <- "SELECT * FROM mtcars WHERE cyl = ?"
dat6 <- dbGetQuery(con, qry, params = list(6L))
dat8 <- dbGetQuery(con, qry, params = list(8L))

至于

dbWriteTable
,对我来说主要是方便快捷的工作。有时 DBI/ODBC 连接在服务器上使用错误的数据类型(例如,SQL Server 的
DATETIME
而不是
DATETIMEOFFSET
;或者
NVARCHAR(32)
varchar(max)
),所以如果我需要快速的东西,我会使用
dbWriteTable
,否则我将使用我知道我想要的服务器数据类型正式定义表,如
dbExecute(con, "create table quux (...)")
。到目前为止,这 not 是“最佳实践”,它很大程度上植根于偏好和便利性。对于简单的数据(浮点数/整数/字符串)并且服务器默认数据类型是可以接受的,
dbWriteTable
非常好。也可以使用
dbCreateTable
(创建它而不上传数据),它允许您指定具有更多控制权的字段。

© www.soinside.com 2019 - 2024. All rights reserved.