可以用 PostgreSQL 执行跨数据库查询吗?

我将根据下面的错误消息(和 这个谷歌搜索结果)猜测答案是“否”,但是是否存在使用 PostgreSQL 执行跨数据库查询的方法?

databaseA=# select * from databaseB.public.someTableName;
ERROR:  cross-database references are not implemented:
"databaseB.public.someTableName"

我正在处理一些跨两个数据库分区的数据,尽管数据实际上是在两个数据库之间共享的(一个数据库中的 userid 列来自另一个数据库中的 users表)。我不知道为什么这是两个独立的数据库而不是模式,但这就是生活..。

295509 次浏览

在我遇到这个问题之前,我得出了和您一样的关于跨数据库查询的结论。最后,我使用模式来划分表空间,这样我可以保持表的分组,但仍然可以查询所有表。

注意: 正如最初的询问者所暗示的那样,如果您在同一台机器上设置两个数据库,那么您可能希望改为设置两个 模式——在这种情况下,您不需要任何特殊的东西来跨越它们进行查询。

postgres_fdw

使用 postgres_fdw(外部数据包装器)连接到任何 Postgres 数据库(本地或远程)中的表。

请注意,有 其他流行数据源的外部数据包装器。在这个时候,只有 postgres_fdwfile_fdw是正式 Postgres 分发的一部分。

用于9.3之前的 Postgres 版本

这种老版本已不再受支持,但如果您需要在2013年之前的 Postgres 安装中这样做,有一个称为 dblink的函数。

我从未使用过它,但它与 PostgreSQL 的其余部分一起维护和发布。如果您正在使用 Linux 发行版附带的 PostgreSQL 版本,那么可能需要安装一个名为 postgreql-Contrib 的软件包。

如果性能很重要,而且大多数查询是只读的,我建议将数据复制到另一个数据库。虽然这看起来像是不需要的数据复制,但是如果需要索引的话,这可能会有所帮助。

这可以通过简单的插入触发器来完成,插入触发器接着调用 dblink 来更新另一个副本。还有成熟的复制选项(比如 Slony) ,但这是跑题了。

是的,您可以通过使用 DBlink (仅 postgreql)和 DBI-Link (允许外部跨数据库查询器)和 TDS _ Link (允许在 MS SQL 服务器上运行查询)来实现。

我以前使用过 DB-Link 和 TDS-link,并取得了很大的成功。

只是为了增加一点信息。

除了当前数据库之外,没有其他查询数据库的方法。由于 PostgreSQL 加载特定于数据库的系统目录,因此不确定跨数据库查询应该如何执行。

Contrib/dblink 允许使用函数调用进行跨数据库查询。当然,客户端也可以同时连接到不同的数据库,并在客户端合并结果。

PostgreSQL 常见问题解答

Dblink () ——在远程数据库中执行查询

Dblink 执行一个查询(通常是一个 SELECT,但也可以是任何 SQL 返回行的语句)。

当给定两个文本参数时,首先将第一个参数查找为 持久连接的名称; 如果找到,则在 如果未找到,则将第一个参数视为 连接信息字符串,以及指示的 仅在此命令期间建立连接。

一个很好的例子:

SELECT *
FROM   table1 tb1
LEFT   JOIN (
SELECT *
FROM   dblink('dbname=db2','SELECT id, code FROM table2')
AS     tb2(id int, code text);
) AS tb2 ON tb2.column = tb1.column;

注意: 我提供此信息以备将来参考

如果有人需要一个关于如何执行跨数据库查询的更复杂的示例,这里有一个清理每个拥有 databasechangeloglock表的数据库的示例:

CREATE EXTENSION IF NOT EXISTS dblink;


DO
$$
DECLARE database_name TEXT;
DECLARE conn_template TEXT;
DECLARE conn_string TEXT;
DECLARE table_exists Boolean;
BEGIN
conn_template = 'user=myuser password=mypass dbname=';


FOR database_name IN
SELECT datname FROM pg_database
WHERE datistemplate = false
LOOP
conn_string = conn_template || database_name;


table_exists = (select table_exists_ from dblink(conn_string, '(select Count(*) > 0 from information_schema.tables where table_name = ''databasechangeloglock'')') as (table_exists_ Boolean));
IF table_exists THEN
perform dblink_exec(conn_string, 'delete from databasechangeloglock');
END IF;
END LOOP;


END
$$

我已经检查并尝试使用 眨眼Postgres _ fdw在两个不同的数据库中的两个表之间创建一个外键关系,但是没有结果。

在阅读了其他人对此的反馈后,例如 给你给你以及其他一些来源,看起来目前还没有办法做到这一点:

眨眼Postgres _ fdw确实能够连接和查询其他数据库中的表,这在标准 Postgres 中是不可能的,但它们不允许在不同数据库中的表之间建立外键关系。

https://www.cybertec-postgresql.com/en/joining-data-from-multiple-postgres-databases/[2017年出版]

现在你也可以选择使用 https://prestodb.io/

您可以在 PrestoDB 节点上运行 SQL,它将根据需要分发 SQL 查询。它可以为不同的数据库连接到同一个节点两次,也可以连接到不同主机上的不同节点。

它不支持:

DELETE
ALTER TABLE
CREATE TABLE (CREATE TABLE AS is supported)
GRANT
REVOKE
SHOW GRANTS
SHOW ROLES
SHOW ROLE GRANTS

因此,您应该只在 SELECT 和 JOIN 需要时使用它。根据上述需要直接连接到每个数据库。(看起来你也可以插入或更新,这很好)

客户端应用程序主要使用 JDBC连接到 PrestoDB,但也可以使用其他类型的连接,包括 与 Tableu 兼容的 web API

这是一个由 Linux 基金会和 Presto 基金会管理的开源工具。

Presto 基金会的创始成员有: Facebook,Uber, 推特和阿里巴巴。

目前的成员有: Facebook,Uber,Twitter,阿里巴巴,Alluxio, Ahana Upsolver 和 Intel。