【问题标题】:How to use DBI::dbConnect() to read and write tables from multiple databases如何使用 DBI::dbConnect() 从多个数据库中读取和写入表
【发布时间】:2020-03-09 16:58:28
【问题描述】:

我有一个使用 DBI::dbConnect 连接的 Netezza SQL 服务器。服务器有多个数据库,我们将命名为 db1 和 db2。

我想尽可能多地使用 dbplyr,而不必在 RODBC::sqlQuery() 中编写 SQL 代码,但我不确定如何执行以下操作:。

1) 如何读取 db1 中的表,对其进行处理并让服务器将结果写入 db2 中的表中,而无需通过我的桌面?
2) 如何在 db1 中的一个表和 db2 中的另一个表之间进行左连接?

看起来可能有一种方法可以连接到数据库 ="SYSTEM" 而不是数据库="db1" 或 "db2",但我不确定下一步是什么。

con <- dbConnect(odbc::odbc(),
             driver = "NetezzaSQL",
             database = "SYSTEM",
             uid = Sys.getenv("netezza_username"),
             pwd = Sys.getenv("netezza_password"),
             server = "NETEZZA_SERVER",
             port = 5480)

【问题讨论】:

  • (1) 您通常可以同时跟踪多个单独的连接,就像在con1 &lt;- DBI::dbConnect(...); con2 &lt;- DBI::dbConnect(...) 中一样,不过由您来管理要使用的连接。一些 DBMS 允许您通过 SQL 本身更改数据库,但许多不允许(例如 mssql)。 (2) 从两个不同的数据库加入 in database 的唯一方法是,如果其中至少一个支持外部数据包装器和/或外部表,并且与 R 无关(并且非常不平凡)。缺少它,将两者都下载到 R 中,然后加入......可能不是你想要/需要的。
  • 感谢 r2evans。我知道如何创建两个连接,从一个读取到我的桌面,在我的桌面上工作并写入另一个,但我真的希望有一些不需要通过我的桌面的东西 - 谢谢你警告我这不是琐碎的 ! :)
  • 我认为您需要先在数据库上建立一个数据库链接。然后它只是与其中一个数据库和一些 SQL 的连接。 oracletutorial.com/oracle-administration/…

标签: r database dbi dbplyr


【解决方案1】:

我使用in_schemadbExecute 在SQL 服务器上解决此问题,如下所示。假设 Netezza 并没有太大的不同。

第 1 部分:共享连接

第一个问题是通过同一个连接连接到两个表。如果我们使用不同的连接,那么连接两个表会导致数据从一个连接复制到另一个连接,这非常慢。

con <- dbConnect(...) # as required by your database

table_1 <- dplyr::tbl(con, from = dbplyr::in_schema("db1", "table_name_1"))
table_2 <- dplyr::tbl(con, from = dbplyr::in_schema("db2.schema2", "table_name_2"))

虽然 in_schema 用于传递架构名称,但您也可以使用它来传递数据库名称(或两者之间用一个点)。

以下内容现在应该可以正常工作了:

# check connection
head(table_1)
head(table_2)

# test join code
left_join(table_1, table_2, by = "id") %>% show_query()
# check left join
left_join(table_1, table_2, by = "id") %>% head()

第 2 部分:写入数据库

一个远程表由两个东西定义

  1. 连接
  2. 当前查询的代码(例如show_query的结果)

我们可以将这些与dbExecute 一起使用来写入数据库。我的例子是SQL server(使用INTO作为关键字,如果sql语法不同,你必须适应自己的环境)。

# optional, extract connection from table-to-save
con <- table_to_save$src$con

# SQL query
sql_query <- paste0("SELECT *\n",
                    "INTO db1.new_table \n", # the database and name you want to save
                    "FROM (\n",
                    dbplyr::sql_render(table_to_save),
                    "\n) subquery_alias")
# run query
dbExecute(con, as.character(sql_query))

这个想法是创建一个可以由数据库执行的查询,该数据库将写入新表。我通过将现有查询视为SELECT ... INTO ... FROM (...) subquery_alias 模式的子查询来做到这一点。

注意事项:

  • 如果show_querysql_render 生成的sql 查询在您直接访问数据库时可以正常工作,那么上面的方法应该可以正常工作(所有的变化是命令是通过R 而不是通过sql 控制台到达的)。李>
  • 可以在here 上找到我为平滑此过程而编写的函数。它们还包括附加、删除、压缩、索引和处理视图。
  • 如果表已经存在于数据库中,通过dbExecute 写表会出错,所以我建议先检查一下。
  • 我在其他地方使用了这个方法,但是用in_schema 插入数据库名称对于创建视图不起作用。要创建(或删除)视图,我必须确保连接到我想要视图的数据库。

【讨论】:

  • 感谢您的来信!阅读此处的术语 (db.rstudio.com/best-practices/schema) 并查看此处的集合窗格 (db.rstudio.com/rstudio/connections),我相信您的解决方案适用于两个表位于同一数据库但架构不同的情况。我的问题是我的表在不同的数据库 中,但在同一台服务器上。它还应该工作吗?
  • 连接到数据库,然后查询第二个确实有效:db1_con
  • 我回答的一个关键点是in_schema可以用来提供数据库名称。这是可行的,因为 R 会将模式名称放在表表 (schema.table) 之前,这与您希望它对数据库名称 (db.table) 执行的操作相同。
猜你喜欢
  • 2020-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-19
相关资源
最近更新 更多