【问题标题】:tbl with in_schema returns "Invalid object name" error带有 in_schema 的 tbl 返回“无效的对象名称”错误
【发布时间】:2021-01-14 07:32:18
【问题描述】:

连接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的。

但是,我想导出上面看到的黄色突出显示的表格。以下代码之前(一个月前)成功,但现在返回错误。

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

错误:nanodbc/nanodbc.cpp:1655:42000:[Microsoft][ODBC Driver 17 for SQL Server][SQL Server]无效的对象名 'DB01WEA84103.dbo.Ad10Min1_Average'。 [Microsoft][ODBC 驱动程序 17 用于 SQL Server][SQL Server]无法准备语句。 '选择 * 从“DB01WEA84103.dbo”。“Ad10Min1_Average”作为“q13” 哪里(0 = 1)'

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

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

那么,我错过了什么?产生错误的 con 和 in_schema 代码如何再次工作?

【问题讨论】:

  • DB01WEA84103.dbo 不是模式,它是 db_name.schema。您可以使用SELECT * FROM [DB01WEA84103].[dbo].[Ad10Min1_Average] WHERE (0 = 1) 之类的方式进行跨数据库查询(授予权限)。不过,您为什么不让事情变得更轻松,并在您的连接中提供 catalog="DB01WEA84103" 以便它位于正确的数据库中?
  • 首先,感谢您的回复。但是有 22 个数据库,我必须访问每个数据库中的表,因此我想创建一个循环。正如你所说,我可以在 dbConnect 函数中添加 database 或 catalog = “DB...” 参数。此外,dbReadTable 函数也可以工作,但考虑到循环,与 tbl 和 in_schema 组合相比,它们非常慢。总之,我只想通过一个连接来访问不同的数据库。

标签: r sql-server odbc database-schema dbplyr


【解决方案1】:

速度上的差异是因为tbl(con, ...) 正在创建远程表的访问点,而dbReadTable(con, ...) 正在将表从 SQL 读取/复制到 R。

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

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

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

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

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

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

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

阅读 in_schema 的 dbplyr 文档 (link) 指定架构和表的名称 "... 将被自动引用;使用 sql() 传递不会被引用。”

因此我建议您尝试:

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

注意事项:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-04
    • 1970-01-01
    相关资源
    最近更新 更多