PostgreSQLでデータベース間クエリを実行できますか?


144

以下のエラーメッセージ(およびこのGoogleの結果)に基づいて、答えは「いいえ」であると推測しますが、PostgreSQLを使用してクロスデータベースクエリを実行する方法はありますか?

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

2つのデータベース間で分割されているデータを使用していますが、データは実際には2つのデータベース間で共有されています(一方のデータベースのユーザーID列は、もう一方のデータベースのusersテーブルから取得されます)。これらがスキーマではなく2つの別個のデータベースである理由はわかりませんが、最も重要なのは...

回答:


111

注:元の質問者が示唆していたように、同じマシンに2つのデータベースを設定する場合は、代わりに2つのスキーマを作成する必要があります。

postgres_fdw

使用postgres_fdwローカルまたはリモート-任意Postgresデータベース内のテーブルに接続する(外部データラッパ)。

他の一般的なデータソースには外部データラッパーがあることに注意してください。この時点で、唯一postgres_fdwfile_fdw公式Postgresのディストリビューションの一部です。

9.3以前のPostgresバージョンの場合

この古いバージョンはサポートされなくなりましたが、2013年より前のPostgresインストールでこれを行う必要がある場合は、 dblink

私はこれを使用したことがありませんが、PostgreSQLの他の部分と一緒に維持および配布されています。Linuxディストリビューションに付属のバージョンのPostgreSQLを使用している場合は、postgresql-contribというパッケージをインストールする必要がある場合があります。


postgresql-contrib前にインストールする必要がありdblinkますか?またはpostgresql-contrib含まれていdblinkますか?そして、OPのクエリは機能しますか、それとも別の方法でクエリする必要がありますか?
mpen 2011年

3
私が読み取れることから、dblinkは2つのデータベースにまたがるクエリが必要な場合を処理しません。
Paul Tomblin

26

dblink() -リモートデータベースでクエリを実行します

dblinkは、リモートデータベースでクエリ(通常はSELECTですが、行を返すSQLステートメントでもかまいません)を実行します。

2つのテキスト引数が指定された場合、最初の引数は最初に永続的な接続の名前として検索されます。見つかった場合、コマンドはその接続で実行されます。見つからない場合、最初の引数はdblink_connectの場合と同様に接続情報文字列として扱われ、指定された接続はこのコマンドの実行中のみ行われます。

良い例の1つ:

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;

注:この情報は今後の参考のために提供します。屈折


21

クロスデータベースクエリについて同じ結論に至る前に、これに遭遇しました。結局のところ、スキーマを使用してテーブルスペースを分割し、テーブルをグループ化したまますべてのクエリを実行できるようにしました。


17
MySQL環境から来ている場合、MySQLがデータベースと呼ぶものは実際にはスキーマ(MySQLではCREATE SCHEMA == CREATE DATABASE)なので、複数のデータベースを使用してMySQLから何かを移植する場合は、スキーマを使用します
MkV

10

もう少し情報を追加します。

現在のデータベース以外にデータベースを照会する方法はありません。PostgreSQLはデータベース固有のシステムカタログをロードするため、データベース間のクエリがどのように動作するかさえ不確かです。

contrib / dblinkでは、関数呼び出しを使用したデータベース間のクエリが可能です。もちろん、クライアントは異なるデータベースに同時に接続して、クライアント側で結果をマージすることもできます。

PostgreSQL FAQ


5
この追加情報は誤解を招く可能性があり、ユーザーが上記のソリューションを使用するのを妨げるかもしれません。
johan855

5

はい。DBlink(postgresqlのみ)とDBI-Link(外部のクロスデータベースクエリアを許可)、およびMS SQLサーバーに対してクエリを実行できるTDS_LInkを使用できます。

以前にDB-LinkとTDS-linkを使用したことがあり、大きな成功を収めています。


2

パフォーマンスが重要で、ほとんどのクエリが読み取り専用である場合、データを別のデータベースに複製することをお勧めします。これは不要なデータの複製のように見えますが、インデックスが必要な場合に役立ちます。

これは、別のコピーを更新するためにdblinkを呼び出す単純なon挿入トリガーで実行できます。本格的なレプリケーションオプション(Slonyなど)もありますが、それは話題外です。


2

クロスデータベースクエリを実行する方法についてより複雑な例が必要な場合に備えて、次の例は、それを含む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
$$

1

私は確認し、dblinkpostgres_fdwの両方を使用して、2つの異なるデータベースの2つのテーブル間に外部キー関係を作成しようとしましたが、結果はありませんでした。

これに関する他の人々のフィードバックを読んだとき、たとえばここここと他のいくつかのソースでは、現在それを行う方法はないようです:

データベース・リンクpostgres_fdw実際に標準のPostgresでは不可能である他のデータベースにすると、クエリのテーブルを接続することを可能に、彼らは別のデータベース内のテーブル間の外部キー関係を確立することはできません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.