制限
システムカタログpg_database
に問い合わせることができます -同じデータベースクラスター内の任意のデータベースからアクセスできます。トリッキーな部分は、CREATE DATABASE
単一のステートメントとしてのみ実行できます。マニュアル:
CREATE DATABASE
トランザクションブロック内では実行できません。
そのため、関数内で直接実行したり、DO
を実行したりすることはできません。 ステートメント。暗黙的にトランザクションブロック内にあります。 Postgres 11で導入されたSQLプロシージャも、これには役立ちません。
psql内からの回避策
DDLステートメントを条件付きで実行することにより、psql内から回避できます。
SELECT 'CREATE DATABASE mydb'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec
マニュアル:
\gexec
現在のクエリバッファをサーバーに送信し、クエリの出力の各行の各列(存在する場合)を実行するSQLステートメントとして扱います。
シェルからの回避策
\gexec
を使用 psqlを1回呼び出すだけです。 :
echo "SELECT 'CREATE DATABASE mydb' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec" | psql
接続には、より多くのpsqlオプションが必要になる場合があります。役割、ポート、パスワード、...参照:
- パスワードなしでpsqlコマンドを使用してバッチファイルを実行する
psql -c "SELECT ...\gexec"
では同じことを呼び出すことはできません \gexec
以降 はpsqlメタコマンドであり、-c
オプションは単一のコマンドを期待します マニュアルには次のように記載されています:
command
サーバーで完全に解析可能な(つまり、psql固有の機能が含まれていない)コマンド文字列か、単一の円記号コマンドのいずれかである必要があります。したがって、-c
内でSQLとpsqlのメタコマンドを混在させることはできません。 オプション。
Postgresトランザクション内からの回避策
dblink
を使用できます トランザクションブロックの外部で実行されている現在のデータベースへの接続。したがって、エフェクトをロールバックすることもできません。
このための追加モジュールdblinkをインストールします(データベースごとに1回):
- PostgreSQLでdblinkを使用(インストール)する方法は?
次に:
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の追加された回答を参照してください:
- PostgreSQLのCREATEDATABASEが存在しない場合はシミュレートしますか?
dblinkの詳細な説明:
- PostgreSQLで大規模な非ブロッキング更新を行うにはどうすればよいですか?
これを繰り返し使用できる機能にすることができます。