带有 in_schema returns "Invalid object name" 错误的 tbl

tbl with in_schema returns "Invalid object name" error

连接到 SQL 服务器后,可以列出其中的数据库。

con = dbConnect(odbc(),
             Driver   = "ODBC Driver 17 for SQL Server",
             Server   = "xxxxxxxxxxxx",
             UID = "xxxxxxxxxxxx",
             PWD = "xxxxxxxxxxxx",
             Port     = xxxxxxxxxxxx)

这里可以找到连接成功

之后,我只想列出此 SQL 服务器中的数据库

databases = dbGetQuery(con, "SELECT name FROM master..sysdatabases")

由于我对SQL不熟悉,看到“con”中有一个已经分配的数据库“DB01CWE5462”,我有点奇怪。该数据库也可以在 dbGetQuery (DB01CWE5462) 的结果中找到。我猜这个数据库是自动分配给con.

但是,我想导出上面看到的黄色突出显示的 table。下面的代码之前(一个月前)是成功的,但现在 returns 出错了。

tbl(con, in_schema("DB01WEA84103.dbo","Ad10Min1_Average"))

Error: nanodbc/nanodbc.cpp:1655: 42000: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Invalid object name 'DB01WEA84103.dbo.Ad10Min1_Average'. [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Statement(s) could not be prepared. 'SELECT * FROM "DB01WEA84103.dbo"."Ad10Min1_Average" AS "q13" WHERE (0 = 1)'

经过一番搜索,我发现了一个解决方案,与上述代码之前成功运行相比,速度相当慢。

dbReadTable(con, 'Ad10Min1_Average', schema='DB01WEA84103.dbo')

那么,我缺少的东西是什么?我应该如何处理 con 和 in_schema 产生错误的代码才能再次运行?

速度上的差异是因为 tbl(con, ...) 正在创建到远程 table 的访问点,而 dbReadTable(con, ...) 是 reading/copying table 来自 SQL 进入 R.

您使用的方法是指定数据库和模式的标准解决方法。我猜想 dbplyr 包已经更新,这意味着这个解决方法现在需要一个额外的步骤。

仔细查看错误消息中的 SQL 会发现原因:

SELECT * FROM "DB01WEA84103.dbo"."Ad10Min1_Average"

请注意 "DB01WEA84103.dbo" 周围的双引号。双引号告诉 SQL 将其视为单个对象:名称为 DB01WEA84103.dbo 的模式,而不是两个对象:名称为 DB01WEA84103 的数据库和名称为 [=18= 的模式].

理想情况下,此查询应为:

SELECT * FROM "DB01WEA84103"."dbo"."Ad10Min1_Average"

现在句号不包含在双引号中。

阅读 in_schema 的 dbplyr 文档 (link) 指定模式名称和 table "... 将自动引用;使用sql() 传递一个不会被引用的原始名称。"

因此我建议您尝试:

tbl(con, in_schema(sql("DB01WEA84103.dbo"),"Ad10Min1_Average"))

备注:

  • SQL中的双引号用于表示单个对象,忽略特殊字符。出于同样的目的,SQL 中经常使用方括号。
  • 在 R 中使用单引号还是双引号不会影响 SQL 代码是否包含双引号。这是由 dbplyr 的翻译方法控制的。
  • 如果您的数据库名称包含特殊字符,请尝试将它们括在方括号中:例如 [my!odd@database#name].[my%unusual&schema*name].