如何从 dplyr::tbl 获取详细的数据库错误消息?

How might I get detailed database error messages from dplyr::tbl?

提问人:Jon 'links in bio' Ericson 提问时间:8/11/2018 最后编辑:CommunityJon 'links in bio' Ericson 更新时间:6/19/2023 访问量:1638

问:

我正在使用 R 绘制我从数据库中提取的一些数据(具体来说,是 Stack Exchange 数据转储):

dplyr::tbl(serverfault, 
           dbplyr::sql("
select year(p.CreationDate) year,
       avg(p.AnswerCount*1.0) answers_per_question,
       sum(iif(ClosedDate is null, 0.0, 100.0))/count(*) close_rate
from Posts p
where PostTypeId = 1
group by year(p.CreationDate)
order by year(p.CreationDate)
"))

查询在 SEDE 上工作正常,但我在 R 控制台中收到此错误:

Error: <SQL> 'SELECT *
FROM (
select year(p.CreationDate) year,
       avg(p.AnswerCount*1.0) answers_per_question,
       sum(iif(ClosedDate is null, 0.0, 100.0))/count(*) close_rate
from Posts p
where PostTypeId = 1
group by year(p.CreationDate)
order by year(p.CreationDate)
) "zzz11"
WHERE (0 = 1)'
  nanodbc/nanodbc.cpp:1587: 42000: [FreeTDS][SQL Server]Statement(s) could not be prepared. 

我估计“无法准备语句”意味着 SQL Server 出于某种原因不喜欢该查询。不幸的是,它没有给出任何关于出了什么问题的提示。在摆弄了一会儿查询后,我注意到根据错误消息,它被包装在一个子选择中。复制并执行由链中的某个库构造的完整查询时,SQL Server 给了我这个信息量更大的错误消息:

除非还指定了 TOP、OFFSET 或 FOR XML,否则 ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效。

现在解决方案很明显:删除(或注释掉)该子句。但是 R 控制台中的详细错误消息在哪里?我正在使用 Rstudio,如果这很重要的话。如果我能在我正在处理的代码旁边获得完整的异常,它将帮助我更快地修复错误。(需要明确的是,我经常从 dplyr::tbl 收到神秘的错误,并且通常使用二进制搜索调试来修复它们。order by

r dplyr dbplyr

评论

0赞 Mako212 8/11/2018
如果您查询 ?这有什么改善吗?DBI::dbGetQuery()dbplyr::sql
2赞 joran 8/11/2018
由于您看到的错误消息是由 nanodbc 直接抛出的,我想知道 dbplyr 对此到底能做多少。我的预感是,这不是通过 R 级别的调整轻松解决的问题。如果是我,我会直接走到马的嘴边,提交一个github问题,这将更直接地到达专家(Jim Hester)。
2赞 Jim 8/11/2018
哦,我不知道SEDE使用什么驱动程序/连接堆栈来显示其错误消息,但是R中的错误来自freeTDS驱动程序,并且是odbc R包的唯一信息。除了使用不同的驱动程序(也许尝试来自 Microsoft 或 RStudio 专业驱动程序的驱动程序)之外,没有办法使此错误更具信息性?
1赞 r2evans 4/28/2022
我认为这已经解决了。当我运行上面的文字代码(SQL Server 2016、DBI-1.1.2、odbc-1.3.3、R-4.1.2)时,我收到完整的详细错误消息, * 不幸的是,我使用的是 mssqlodbc 本身,而不是 freetds(从未发现它稳定),所以我不能排除它是特定于驱动程序的还是通用的。@JonEricson,您能确认该错误是否仍然出现在 FreeTDS 中吗?如果没有,我建议这个问题可以关闭或自我回答,因为可以通过更新解决。The ORDER BY clause ... is also specified.*dbplyr
2赞 Jon 'links in bio' Ericson 4/28/2022
@r2evans:好久不见了。;-)如果我有机会在我的新机器上重现这个问题,我很乐意自我回答。

答:

-6赞 Ganesh Kadam 6/19/2023 #1

要从 dplyr::tbl 获取更详细的错误消息,您可以修改代码以包含 tryCatch() 函数。此功能允许您捕获和处理错误,包括提取详细的错误消息。 尝试修改代码,如下所示。

result <- tryCatch({
  dplyr::tbl(serverfault, 
             dbplyr::sql("
               select year(p.CreationDate) year,
                      avg(p.AnswerCount*1.0) answers_per_question,
                      sum(iif(ClosedDate is null, 0.0, 100.0))/count(*) close_rate
               from Posts p
               where PostTypeId = 1
               group by year(p.CreationDate)
               order by year(p.CreationDate)
             "))
}, error = function(e) {
  message("Detailed error message: ", conditionMessage(e))
  stop(e)
})

# Continue with your code using the `result` object if no error occurred

在修改后的代码中,tryCatch() 函数包装了 dplyr::tbl() 调用。在 tryCatch() 函数中,使用 error 参数定义错误处理程序。在错误处理程序中,您可以使用 conditionMessage() 函数访问详细的错误消息。

如果发生错误,错误处理程序将使用 message() 将详细的错误消息打印到控制台,然后使用 stop(e) 重新引发错误以停止执行进一步的代码。如果未发生错误,代码将继续使用 result 对象。

此方法允许您在使用 dplyr::tbl 或其他可能引发错误的函数时捕获和显示详细的错误消息。

评论

0赞 Peter Mortensen 9/30/2023
这在博客文章为什么 AI 是 Stack Overflow 上的问题”(靠近“果然”)中被引用。