web-dev-qa-db-ja.com

PostgreSQLで制約を変更しようとしています

Oracleが提供するドキュメントを確認し、テーブルを削除せずに制約を変更する方法を見つけました。問題は、キーワードを認識しないため、変更時にエラーになることです。

EMS PostgreSQL用のSQLマネージャー。

Alter table public.public_insurer_credit MODIFY CONSTRAINT public_insurer_credit_fk1
    deferrable, initially deferred;

を使用して制約を削除することで回避できました:

ALTER TABLE "public"."public_insurer_credit"
  DROP CONSTRAINT "public_insurer_credit_fk1" RESTRICT;

ALTER TABLE "public"."public_insurer_credit"
  ADD CONSTRAINT "public_insurer_credit_fk1" FOREIGN KEY ("branch_id", "order_id", "public_insurer_id")
    REFERENCES "public"."order_public_insurer"("branch_id", "order_id", "public_insurer_id")
    ON UPDATE CASCADE
    ON DELETE NO ACTION
    DEFERRABLE 
    INITIALLY DEFERRED;

正しいマニュアル(PostgreSQLから提供されている、Oracleによるnot)によると、ALTER TABLEステートメントで使用可能な変更制約はありません。

正しいマニュアルへのリンクは次のとおりです。

http://www.postgresql.org/docs/current/static/sql-altertable.html

34

Postgresには制約のためのALTERコマンドはありません。これを実現する最も簡単な方法は、drop制約を使用し、目的のパラメーターを使用して再度追加することです。もちろん、制約の変更は現在のテーブルデータに対して実行されます。

BEGIN;
ALTER TABLE t1 DROP CONSTRAINT ...
ALTER TABLE t1 ADD CONSTRAINT ...
COMMIT;
82
Chris Cashwell

バージョン9.4以降、PostgreSQLはALTER TABLE ... ALTER CONSTRAINT外部キー用。

この機能は"Allow constraint attributes to be altered, so the default setting of NOT DEFERRABLE can be altered to DEFERRABLE and back."あなたの質問を見ると、それがあなたが探していたものであると思います。

より詳細な情報と例はここにあります:
http://www.depesz.com/2013/06/30/waiting-for-9-4-alter-table-alter-constraint-for-fks/

31
mkurz

ALTER CONSTRAINTでは、外部キー名を知る必要がありますが、これは必ずしも便利ではありません。

関数は次のとおりです。テーブル名と列名のみを知る必要があります。使用法:

select replace_foreign_key('user_rates_posts', 'post_id', 'ON DELETE CASCADE');

関数:

CREATE OR REPLACE FUNCTION 
    replace_foreign_key(f_table VARCHAR, f_column VARCHAR, new_options VARCHAR) 
RETURNS VARCHAR
AS $$
DECLARE constraint_name varchar;
DECLARE reftable varchar;
DECLARE refcolumn varchar;
BEGIN

SELECT tc.constraint_name, ccu.table_name AS foreign_table_name, ccu.column_name AS foreign_column_name 
FROM 
    information_schema.table_constraints AS tc 
    JOIN information_schema.key_column_usage AS kcu
      ON tc.constraint_name = kcu.constraint_name
    JOIN information_schema.constraint_column_usage AS ccu
      ON ccu.constraint_name = tc.constraint_name
WHERE constraint_type = 'FOREIGN KEY' 
   AND tc.table_name= f_table AND kcu.column_name= f_column
INTO constraint_name, reftable, refcolumn;

EXECUTE 'alter table ' || f_table || ' drop constraint ' || constraint_name || 
', ADD CONSTRAINT ' || constraint_name || ' FOREIGN KEY (' || f_column || ') ' ||
' REFERENCES ' || reftable || '(' || refcolumn || ') ' || new_options || ';';

RETURN 'Constraint replaced: ' || constraint_name || ' (' || f_table || '.' || f_column ||
 ' -> ' || reftable || '.' || refcolumn || '); New options: ' || new_options;

END;
$$ LANGUAGE plpgsql;

注意:この関数コピーしない初期外部キーの属性。外部テーブル名/列名のみを取り、現在のキーを削除し、replacesを新しいキーに置き換えます。

5