15

PostgreSQL9.1を使用しています。

common.client_contactこのコードを使用して外部キーを作成したテーブルがあります。

ALTER TABLE common.client_contact 
ADD FOREIGN KEY (contact_id) REFERENCES common.contact_item(id);

このコードを実行すると、異なる名前(、、など)の外部キーがいくつか取得さclient_contact_contact_id_fkey1れます。client_contact_contact_id_fkey2client_contact_contact_id_fkey3

したがって、新しい制約を作成する前に、それが存在するかどうかを確認する必要があります。

この制約がpg_constraintテーブルに存在するかどうかを確認します。

SELECT * FROM pg_constraint WHERE conname = 'client_contact_contact_id_fkey'

そして今、私はそれらを一緒に組み合わせる必要があります。何かのようなもの

IF NOT EXISTS
    (SELECT * FROM pg_constraint WHERE conname = 'client_contact_contact_id_fkey')
ALTER TABLE common.client_contact
    ADD CONSTRAINT client_contact_contact_id_fkey
    FOREIGN KEY (contact_id) REFERENCES common.contact_item(id)

あるいは単に

ALTER TABLE common.client_contact 
ADD FOREIGN KEY IF NOT EXISTS (contact_id) REFERENCES common.contact_item(id)

ただし、これら2つのクエリは構文エラーを生成します。では、PostgreSQLでどのようにそれを行うことができますか?

4

3 に答える 3

27

ブロックを使用しDOて、PL/PgSQLで実行します。

DO $$
BEGIN
    IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'client_contact_contact_id_fkey') THEN
        ALTER TABLE common.client_contact
            ADD CONSTRAINT client_contact_contact_id_fkey
            FOREIGN KEY (contact_id) REFERENCES common.contact_item(id);
    END IF;
END;
$$;

デフォルトの制約名の生成に依存しているようですが、これは理想的ではありません。information_schema2つの列をリンクする制約の存在を確認するために使用する方がおそらく安全です。

次のクエリは、生成された制約名に依存せずに、2つのテーブル間の外部キーをチェックします。

SELECT 1
FROM information_schema.table_constraints tc 
INNER JOIN information_schema.constraint_column_usage ccu 
  USING (constraint_catalog, constraint_schema, constraint_name) 
INNER JOIN information_schema.key_column_usage kcu 
  USING (constraint_catalog, constraint_schema, constraint_name) 
WHERE constraint_type = 'FOREIGN KEY' 
  AND ccu.table_name = 'contact_item' 
  AND ccu.table_schema = 'common'  
  AND ccu.column_name = 'contact_id' 
  AND tc.table_schema = 'common' 
  AND tc.table_name = 'client_contact'
  AND kcu.column_name = 'id';
于 2012-10-12T09:15:44.503 に答える
7

発生している問題を回避する1つの方法は、制約を作成する前に制約を削除することです。

ALTER TABLE common.client_contact DROP CONSTRAINT IF EXISTS  client_contact_contact_id_fkey; 

ALTER TABLE common.client_contact
    ADD CONSTRAINT client_contact_contact_id_fkey
    FOREIGN KEY (contact_id) REFERENCES common.contact_item(id)

名前付き制約の追加は成功します。

于 2017-04-03T18:33:53.940 に答える
-7

これがうまくいくかどうかはわかりませんが、試すことができます。

クエリを実行する前に起動します

SET FOREIGN_KEY_CHECKS=0

次に、クエリを実行して

SET FOREIGN_KEY_CHECKS=1
于 2012-10-12T09:14:18.960 に答える