170

根据以下错误消息(以及此 Google 结果),我猜测答案是否定的,但无论如何使用 PostgreSQL 执行跨数据库查询?

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

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

4

9 回答 9

135

注意:正如最初的提问者暗示的那样,如果您在同一台机器上设置两个数据库,您可能想要创建两个模式- 在这种情况下,您不需要任何特殊的东西来查询它们。

postgres_fdw

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

请注意,其他流行数据源也有外来数据包装器。目前,只有postgres_fdwfile_fdw是官方 Postgres 发行版的一部分。

对于 9.3 之前的 Postgres 版本

不再支持这个旧版本,但如果您需要在 2013 年之前的 Postgres 安装中执行此操作,则有一个名为dblink.

我从未使用过它,但它与 PostgreSQL 的其余部分一起维护和分发。如果您使用的是 Linux 发行版附带的 PostgreSQL 版本,您可能需要安装一个名为 postgresql-contrib 的包。

于 2008-09-05T18:10:20.070 回答
45

dblink() -- 在远程数据库中执行查询

dblink 在远程数据库中执行查询(通常是 SELECT,但它可以是任何返回行的 SQL 语句)。

当给出两个文本参数时,首先查找第一个作为持久连接的名称;如果找到,则在该连接上执行该命令。如果未找到,则第一个参数将被视为连接信息字符串,就像 dblink_connect 一样,并且仅在此命令的持续时间内建立指示的连接。

一个很好的例子:

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;

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

于 2014-11-21T04:29:36.567 回答
24

在得出与您一样的跨数据库查询结论之前,我已经遇到过这个问题。我最终做的是使用模式来划分表空间,这样我就可以将表分组但仍然查询它们。

于 2008-09-05T17:17:56.157 回答
10

只是为了添加更多信息。

除了当前数据库之外,没有其他方法可以查询数据库。因为 PostgreSQL 加载特定于数据库的系统目录,所以甚至不确定跨数据库查询应该如何表现。

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

PostgreSQL 常见问题

于 2010-05-06T21:10:59.850 回答
5

是的,您可以使用 DBlink(仅限 postgresql)和 DBI-Link(允许外部跨数据库查询器)和 TDS_LInk,它允许对 MS SQL 服务器运行查询。

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

于 2008-09-22T05:47:10.563 回答
3

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

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

于 2008-09-12T15:56:31.940 回答
2

我已经检查并尝试使用dblinkpostgres_fdw在 2 个不同数据库中的 2 个表之间创建外键关系,但没有结果。

阅读了其他人对此的反馈,例如这里这里以及其他一些来源,目前似乎没有办法做到这一点:

dblinkpostgres_fdw确实可以连接和查询其他数据库中的表,这是标准 Postgres 无法做到的,但它们不允许在不同数据库中的表之间建立外键关系。

于 2019-07-12T13:32:56.570 回答
2

请参阅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、Twitter 和阿里巴巴。

目前的成员有:Facebook、Uber、Twitter、阿里巴巴、Alluxio、Ahana、Upsolver 和英特尔。

于 2021-02-06T15:55:53.380 回答
1

如果有人需要有关如何进行跨数据库查询的更复杂的示例,这里有一个示例,它清理了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
$$
于 2019-04-12T13:58:21.440 回答