断开R中函数内的DBI/RSQLite

Sco*_*man 3 r rsqlite r-dbi

我正在构建一个用于内部使用的包,并试图从用户中抽象出所有可能的数据库交互.我需要连接到数据库并断开与函数内的数据库的连接(我认为).但是,断开连接不起作用.

`my_func = function(){
    con = DBI::dbConnect(RSQLite::SQLite(), 'db_location.sqlite')
    r = DBI::dbSendQuery("SELECT * ...")
    dat = DBI::dbFetch(r)
    DBI::dbDisconnect(con)
    return(dat)
}`
Run Code Online (Sandbox Code Playgroud)

如果你调用这个函数: MY_LIBRARY::my_func()

返回数据但连接未终止并显示警告.

`Warning message:
In connection_release(conn@ptr) :
    There are 1 result in use. The connection will be released when 
    they are closed`
Run Code Online (Sandbox Code Playgroud)

r2e*_*ans 8

SQL查询通常是一个三步过程(忽略连接管理):

  1. 发送查询,接受返回的"结果"对象
  2. 使用"result"对象获取结果
  3. 清除"结果"对象

第三步很重要,因为未清除它代表了为该查询保留的资源.某些数据库连接不允许多个同时未清除的结果,一次只允许一个查询.

这在历史上已经完成:

res <- dbSendQuery(con, "SELECT ...")
dat <- dbFetch(res)
dbClearResult(res)
Run Code Online (Sandbox Code Playgroud)

前段时间(不知道版本),DBI提供了一个强大的便利功能,可以将所有这三行改为一行代码:

dat <- dbGetQuery(con, "SELECT ...")
Run Code Online (Sandbox Code Playgroud)

当查询未返回数据时,此函数不适用,例如,UPDATE或者INSERT,在这种情况下,您应该使用dbSendStatement(可选地后跟dbGetRowsAffected)或dbExecute(自动调用dbGetRowsAffected).

你应该使用dbGetQuery发送数据,返回查询的时候,当您使用SQL参数(以缓解SQL注入).相反,你将返回使用dbSendQuery,dbBind(对于参数)dbFetch,和dbClearResult.

  • 感谢您的详细回复。我想补充一点,最近的 DBI 支持“dbQuery()”的“params”参数用于参数化查询,这将在幕后调用“dbBind()”。 (2认同)