我使用RODBC和R和knitr使用各种生产数据库进行一些报告。在其中一些报告中,我对多个数据库运行了多次查询。
我的每个查询都是以以下形式执行的:
get.total.orders <- function(db.connex.string, start.date, end.date){
db.connex <- odbcDriverConnect(db.connex.string)
ord.qry <- sprintf("SELECT ord_OrderReference AS 'order.ref',
ord_RegisterDate as 'register.date'
FROM Orders
WHERE ord_RegisterDate >= '%s' AND ord_RegisterDate < '%s'",
start.date, end.date)
orders <- sqlQuery(db.connex, ord.qry)
odbcClose(db.connex)
return(orders)
}
请注意,在此函数中打开和关闭ODBC通道,并且在通道的打开和关闭之间只运行一个简单的查询。
尽管如此,当我多次运行报告时(例如在编制报告时),我会收到以下警告:
Warning: closing unused RODBC handle 41
我运行报告的次数越多,错误中报告的句柄数就越高。
为什么,如果我在查询功能中打开和关闭频道,我是否处于打开状态,未使用的&#39; RODBC处理?
更重要的是,我该如何避免这个问题?
答案 0 :(得分:4)
我会使用on.exit
来避免这种情况:
get.total.orders <- function(db.connex.string, start.date, end.date){
db.connex <- odbcDriverConnect(db.connex.string)
on.exit(odbcClose(db.connex)) # <----------------------- change here
ord.qry <- sprintf("SELECT ord_OrderReference AS 'order.ref',
ord_RegisterDate as 'register.date'
FROM Orders
WHERE ord_RegisterDate >= '%s' AND ord_RegisterDate < '%s'",
start.date, end.date)
orders <- sqlQuery(db.connex, ord.qry)
return(orders)
}
这样,即使出现错误,连接也会关闭。另请参阅?on.exit
。
以上假定句柄未关闭,因为执行查询时出错。如果查询没问题,但句柄没有关闭,那我就不知道了。如果成功,odbcClose
将返回0,因此您可以检查它。
正如其他人所指出的那样,这可能没有什么可担心的 - 另一方面,如果明确告诉它关闭,找出连接未关闭的原因仍然很有意思。也许这只是毫秒的问题,并且在分配结果时查询尚未完成。这对我来说没有多大意义,好像结果被分配给orders
那么还有什么关于数据库的呢?但也许有一些东西。在这种情况下,人们可能会试着给它一些时间,例如。
#...
orders <- sqlQuery(db.connex, ord.qry)
orders # or force(orders) - to just evaluate the result once more
Sys.sleep(0.01) # give it 10 milliseconds
orders # or return(orders) - to return the result
# presuming on.exit as before - so odbcClose will happen here too
}
这听起来真的很愚蠢,但如果真的有用,我也不会太惊讶。
另一个想法是,如果您正在使用Rstudio,那么您可能会收到一些幻像错误消息,例如,当第一次使用plot
与不存在的图形参数时,然后没有错误在第二次。
plot(1, bimbo=2) # here you get some warnings as bimbo is not a graphical parameter
plot(2) # nothing wrong here but RStudio replays the previous warnings
对于db处理程序可能会发生类似的情况 - 如果是这种情况,看看你是否在RStudio和控制台(Windows中的Rgui或Rterm或在linux中的终端中运行R)中获得相同的警告将是有益的。当然,如果您使用Rstudio,那当然适用。
最后,您可以尝试在r-help上发布此内容,因为Brian Ripley(RODBC的作者之一)就在那里但不在这里。
所以如你所见,我没有真正的答案,如果需要花费太多精力来解决它,我建议不要担心它:)
答案 1 :(得分:2)
如果连接上存在打开的事务,则函数odbcClose()
将失败。在这种情况下,此连接将保持打开状态。