PostgreSQL でクロスデータベース クエリを実行できますか?
-
09-06-2019 - |
質問
以下のエラー メッセージに基づいて、答えは「いいえ」であると推測します (そして このGoogleの結果)しかし、PostgreSQLを使用してクロスデータベースクエリを実行する方法はありますか?
databaseA=# select * from databaseB.public.someTableName;
ERROR: cross-database references are not implemented:
"databaseB.public.someTableName"
データは実際には 2 つのデータベース間で共有されていますが、2 つのデータベース間でパーティション化されたデータを操作しています (1 つのデータベースの userid 列は users
他のデータベースのテーブル)。なぜこれらがスキーマではなく 2 つの別個のデータベースなのかはわかりませんが、まあまあです...
解決
注記:元の質問者が示唆したように、同じマシン上に 2 つのデータベースをセットアップする場合は、おそらく 2 つのデータベースを作成する必要があるでしょう。 スキーマ 代わりに - その場合、それらに対してクエリを実行するために特別なものは必要ありません。
9.3 以降のアップデート
新しいものを使用できるようになりました postgres_fdw
(外部データ ラッパー) を使用して、ローカルまたはリモートの任意の Postgres データベース内のテーブルに接続します。
があることに注意してください。 他の一般的なデータ ソースの外部データ ラッパー. 。現時点では、唯一、 postgres_fdw
そして file_fdw
これらは公式の Postgres ディストリビューションの一部です。
9.3 より前の元の回答
この機能はデフォルトの PostgreSQL インストールには含まれていませんが、追加することができます。それは呼ばれています dblink
.
私はこれを使用したことはありませんが、PostgreSQL の残りの部分とともに保守および配布されています。Linux ディストリビューションに付属の PostgreSQL のバージョンを使用している場合は、postgresql-contrib というパッケージのインストールが必要になる場合があります。
他のヒント
クロスデータベースクエリについてあなたと同じ結論に達する前に、私はこれに遭遇しました。私が最終的にやったのは、スキーマを使用してテーブルスペースを分割することで、テーブルをグループ化したまますべてのテーブルにクエリを実行できるようにすることでした。
dblink() -- リモート データベースでクエリを実行します
DBLINKはクエリ(通常は選択されていますが、リモートデータベースで行を返す任意の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;
注記:今後の参考のためにこの情報を提供します。 参照
もう少し情報を追加します。
現在のデータベース以外のデータベースにクエリを実行する方法はありません。PostgreSQL はデータベース固有のシステム カタログをロードするため、データベース間のクエリがどのように動作するかさえ不確かです。
contrib/dblink では、関数呼び出しを使用したクロスデータベース クエリが可能です。もちろん、クライアントは異なるデータベースに同時に接続し、クライアント側で結果をマージすることもできます。
はい、DBlink (postgresql のみ)、DBI-Link (外部クロスデータベース クエリアを許可)、および MS SQL サーバーに対してクエリを実行できる TDS_LInk を使用することで可能です。
私は以前 DB-Link と TDS-link を使用して大成功を収めました。
パフォーマンスが重要で、ほとんどのクエリが読み取り専用である場合は、データを別のデータベースにレプリケートすることをお勧めします。これはデータの不必要な重複のように見えますが、インデックスが必要な場合には役立つ可能性があります。
これは、dblink を呼び出して別のコピーを更新する単純な挿入トリガーで実行できます。本格的なレプリケーション オプション (Slony など) もありますが、それは本題から外れます。
データベース間のクエリを実行する方法について、より複雑な例が必要な場合に備えて、以下にクリーンアップする例を示します。 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
$$