PostgreSQL 9.1 では、ロールがすでに存在する場合、CREATE ROLE を使用したロールの作成は失敗します。この制限により、データベースの作成とロール管理のスクリプトを作成するときに問題が生じます。望ましい解決策は、ロールが存在しない場合にのみ CREATE ROLE ステートメントを条件付きで実行することです。
1 つのアプローチは、PL/pgSQL の DO ブロックと IF EXISTS 条件を利用することです。 :
DO $do$ BEGIN IF EXISTS ( SELECT FROM pg_catalog.pg_roles WHERE rolname = 'my_user') THEN RAISE NOTICE 'Role "my_user" already exists. Skipping.'; ELSE CREATE ROLE my_user LOGIN PASSWORD 'my_password'; END IF; END $do$;
このスクリプトは、SELECT を使用してロールの存在を動的にチェックし、実行しますロールが存在しない場合にのみ、ロールを作成してください。
このソリューションでは競合状態が発生しません。 IF EXISTS 条件により、チェック時にロールが存在しない場合にのみロールが作成されることが保証されます。ロールは CREATE ROLE の実行時にすでに存在しているため、チェックと作成の間にロールを作成する同時トランザクションは問題を引き起こしません。
スクリプトをさらに最適化するには、ネストされたブロックを使用して例外ハンドラーのコストを回避できます:
DO $do$ BEGIN IF EXISTS ( SELECT FROM pg_catalog.pg_roles WHERE rolname = 'my_user') THEN RAISE NOTICE 'Role "my_user" already exists. Skipping.'; ELSE BEGIN -- nested block CREATE ROLE my_user LOGIN PASSWORD 'my_password'; EXCEPTION WHEN duplicate_object THEN RAISE NOTICE 'Role "my_user" was just created by a concurrent transaction. Skipping.'; END; END IF; END $do$;
これスクリプトはチェックを効率的に実行し、最小限のオーバーヘッドで潜在的な競合状態を処理します。ネストされたブロックにより、ロールが存在しない場合、または同時トランザクションによって作成されたばかりの場合にのみロールが作成され、その場合には通知が発行されます。
以上がエラーを回避するために条件付きで PostgreSQL ロールを作成するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。