如果外键不存在,如何创建外键?

时间:2012-10-12 09:03:51

标签: postgresql postgresql-9.1

我正在使用PostgreSQL 9.1。

我有一个表common.client_contact,我用这段代码创建了外键:

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

如果我执行此代码,我将获得几个具有不同名称的外键(例如client_contact_contact_id_fkey1client_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)

但是这两个查询都会产生语法错误。那么,我怎样才能在PostgreSQL中做到这一点?

3 个答案:

答案 0 :(得分:20)

使用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_schema检查是否存在链接两列的约束可能更安全。

以下查询检查两个表之间的外键,而不依赖于生成的约束名称:

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';

答案 1 :(得分:1)

解决您遇到的问题的一种方法是在创建约束之前删除约束

ALTER TABLE common.client_contact DROP CONSTRAINT IF EXISTS client_contact_contact_id_fkey;

ALTER TABLE common.client_contact     添加约束client_contact_contact_id_fkey     FOREIGN KEY(contact_id)REFERENCES common.contact_item(id)

添加指定的约束将通过。

答案 2 :(得分:-5)

我不确定这是否有效,但您可以试试。

在您进行查询之前触发

SET FOREIGN_KEY_CHECKS=0

然后你进行查询和

SET FOREIGN_KEY_CHECKS=1