1. ホーム
  2. sql

[解決済み] PostgreSQLのCREATE DATABASE IF NOT EXISTSをシミュレートしてみませんか?

2022-03-12 09:26:42

質問

JDBCで存在しないデータベースを作りたいのですが、どうすればいいですか?PostgreSQLは、MySQLと異なり、JDBCをサポートしていません。 create if not exists 構文があります。これを達成するための最良の方法は何ですか?

アプリケーションは、データベースが存在するかどうかを知りません。データベースが存在するかどうかを確認し、存在する場合はそれを使用する必要があります。したがって、目的のデータベースに接続し、データベースが存在しないために接続に失敗した場合は、新しいデータベースを作成するのが理にかなっています(デフォルトの postgres データベース)。Postgresが返すエラーコードを確認しましたが、同じ種族の関連するコードは見つかりませんでした。

これを実現する別の方法として、接続先が postgres データベースが存在するかどうかを確認し、それに応じてアクションを起こします。2つ目は、ちょっと面倒な作業ですね。

この機能をPostgresで実現する方法はないのでしょうか?

どのように解決するのですか?

制限事項

システムカタログに問い合わせることができます pg_database - 同じデータベースクラスタ内のどのデータベースからでもアクセスできます。厄介なのは CREATE DATABASE は1つの文としてしか実行できない。 マニュアルです。

<ブロッククオート

CREATE DATABASE はトランザクションブロックの中では実行できません。

そのため、関数の内部で直接実行することはできませんし DO ステートメントで、暗黙のうちにトランザクションブロックの中に入ることになります。SQLプロシージャはPostgres 11で導入されました。 にも対応できません。 .

psql内部からの回避策

DDL 文を条件付きで実行することにより、psql 内から回避することができます。

SELECT 'CREATE DATABASE mydb'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec

マニュアルです。

\gexec

現在のクエリバッファをサーバに送信し、クエリの出力の各行の各列(もしあれば)を、実行すべきSQL文として扱います。

シェルからの回避策

\gexec を呼び出すだけです。 一度だけ :

echo "SELECT 'CREATE DATABASE mydb' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec" | psql

接続には、ロール、ポート、パスワードなど、より多くのpsqlオプションが必要な場合があります。参照してください。

で呼び出すことはできません。 psql -c "SELECT ...\gexec" というのは \gexec は psql のメタコマンドであり -c オプションは、1つの コマンド に対して とマニュアルに記載されています。

command は、サーバーが完全に解析可能なコマンド文字列 (つまり、psql 固有の機能を含まない) か、シングルバックスラッシュコマンドのいずれかでなければなりません。したがって、SQL と psql のメタコマンドを -c オプションで指定します。

Postgresのトランザクション内からの回避策

を使用することができます。 dblink これはトランザクションブロックの外側で実行されます。そのため、エフェクトをロールバックすることはできません。

このために追加モジュールdblinkをインストールします(データベースごとに1回)。

では

DO
$do$
BEGIN
   IF EXISTS (SELECT FROM pg_database WHERE datname = 'mydb') THEN
      RAISE NOTICE 'Database already exists';  -- optional
   ELSE
      PERFORM dblink_exec('dbname=' || current_database()  -- current db
                        , 'CREATE DATABASE mydb');
   END IF;
END
$do$;

繰り返しになりますが、接続にはさらに多くの psql オプションが必要な場合があります。Ortwinの追加回答を参照してください。

dblinkの詳細説明です。

これを関数にして繰り返し使うことができます。