我正在使用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_fkey1
,client_contact_contact_id_fkey2
,client_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中做到这一点?
答案 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