2011-11-30 19 views
32

Oracleが提供するドキュメントをチェックして、テーブルを削除せずに制約を変更する方法を見つけました。問題は、キーワードを認識しないため、修正時にエラーが発生することです。PostgreSQLの制約を修正しようとしています

EMS SQLマネージャをPostgreSQL用に使用する。

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; 
+9

なぜPostgreSQLを使用しているときに、Oracleのマニュアルをチェックしていますか(この質問に 'plsql'というタグを付けます)正確なエラーは何ですか(キーワードは認識されません)。 – Bruno

+0

ERROR:構文エラーで、または近くに "MODIFY" LINE 1:ALTER TABLEのpublic.public_insurer_credit CONSTRAINT pを... MODIFY ^ (0.359秒) – MISMajorDeveloperAnyways

+7

のPostgres用のOracleのドキュメントをチェックして、Postgresのを非難。エピック。 –

答えて

23

(オラクルによるPostgreSQLで供給され、ない)正しいマニュアルによると、何も変更はありませんALTER TABLE文で利用可能な制約:

ここでは、正しいマニュアルへのリンクです:

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

+0

適切なドキュメントへのリンクをありがとうございます。私はDBAからOracle PL/SQLのドキュメントを入手しました。数字。 – MISMajorDeveloperAnyways

+2

OracleとOracleのPL/SQLは全く異なるものです。これらの唯一の理由は、OracleのPL/SQL(および他のOracle互換機能)をサポートするEnterpriseDBの* Advanced Server *を使用しているためです。しかし、彼らはあなたにOracleマニュアルではなく、EnterpriseDBのマニュアルを与えておくべきでした –

+1

誰もこの答えにdownvoteがある理由を説明できますか? –

52

Postgresには、制約のためのコマンドがありません。ALTERこれを達成する最も簡単な方法は、に制約をドロップし、それに所望のパラメータを再追加することです。もちろん、制約の変更は現在のテーブルデータに対して実行されます。

BEGIN; 
ALTER TABLE t1 DROP CONSTRAINT ... 
ALTER TABLE t1 ADD CONSTRAINT ... 
COMMIT; 
+14

+1してください。 –

+5

注意:私が正しく理解していれば、DDLステートメントはテーブルのAccessExclusiveロックを取るので、これらのコマンドが長時間かかると、サイトはコマンドが完了するまで停止するようになります。 [documentation page](http://www.postgresql.org/docs/current/static/sql-altertable.html)には、自動的にインデックスを生成するのではなく、明示的にインデックスを指定する方法など、詳細があります。 –

25

バージョン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/

+2

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

+1

9.4ドキュメントでは、「現在のところ、外部キー制約のみが変更される可能性があります。 –

+0

@MichaelHerrmann私はすでに私の答えでこれを言及しました。 – mkurz

2

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; 

は注意してください:この機能は、最初の外部キーの属性をコピーしません。 外部テーブル名/カラム名のみを取り、現在のキーを削除し、を新しいものに置き換えます。

+0

非常に興味深い解決策 – tom10271

関連する問題