如何添加“删除级联”约束?
在PostgreSQL 8中,可以在下表中添加“删除级联”到两个外键而不丢弃后者?
# \d pref_scores Table "public.pref_scores" Column | Type | Modifiers ---------+-----------------------+----------- id | character varying(32) | gid | integer | money | integer | not null quit | boolean | last_ip | inet | Foreign-key constraints: "pref_scores_gid_fkey" FOREIGN KEY (gid) REFERENCES pref_games(gid) "pref_scores_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id)
这两个引用的表格如下:
# \d pref_games Table "public.pref_games" Column | Type | Modifiers ----------+-----------------------------+---------------------------------------------------------- gid | integer | not null default nextval('pref_games_gid_seq'::regclass) rounds | integer | not null finished | timestamp without time zone | default now() Indexes: "pref_games_pkey" PRIMARY KEY, btree (gid) Referenced by: TABLE "pref_scores" CONSTRAINT "pref_scores_gid_fkey" FOREIGN KEY (gid) REFERENCES pref_games(gid)
和这里:
# \d pref_users Table "public.pref_users" Column | Type | Modifiers ------------+-----------------------------+--------------- id | character varying(32) | not null first_name | character varying(64) | last_name | character varying(64) | female | boolean | avatar | character varying(128) | city | character varying(64) | login | timestamp without time zone | default now() last_ip | inet | logout | timestamp without time zone | vip | timestamp without time zone | mail | character varying(254) | Indexes: "pref_users_pkey" PRIMARY KEY, btree (id) Referenced by: TABLE "pref_cards" CONSTRAINT "pref_cards_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_catch" CONSTRAINT "pref_catch_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_chat" CONSTRAINT "pref_chat_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_game" CONSTRAINT "pref_game_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_hand" CONSTRAINT "pref_hand_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_luck" CONSTRAINT "pref_luck_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_match" CONSTRAINT "pref_match_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_misere" CONSTRAINT "pref_misere_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_money" CONSTRAINT "pref_money_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_pass" CONSTRAINT "pref_pass_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_payment" CONSTRAINT "pref_payment_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_rep" CONSTRAINT "pref_rep_author_fkey" FOREIGN KEY (author) REFERENCES pref_users(id) TABLE "pref_rep" CONSTRAINT "pref_rep_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_scores" CONSTRAINT "pref_scores_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_status" CONSTRAINT "pref_status_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id)
另外我想知道是否有意义的增加2个指标到前表?
更新:谢谢,也有我在邮件列表中的build议,我可以在1语句pipe理它,因此不需要交易:
ALTER TABLE public.pref_scores DROP CONSTRAINT pref_scores_gid_fkey, ADD CONSTRAINT pref_scores_gid_fkey FOREIGN KEY (gid) REFERENCES pref_games(gid) ON DELETE CASCADE;
我敢肯定,你不能简单地添加on delete cascade
到现有的外键约束。 您必须先删除约束,然后添加正确的版本。 在标准的SQL中,我相信最简单的方法是
- 开始交易,
- 放下外键,
-
on delete cascade
添加一个外键,最后 - 提交交易
重复你想改变的每个外键。
但是PostgreSQL有一个非标准扩展,可以让你在一个SQL语句中使用多个约束条款。 例如
alter table public.pref_scores drop constraint pref_scores_gid_fkey, add constraint pref_scores_gid_fkey foreign key (gid) references pref_games(gid) on delete cascade;
如果您不知道要删除的外键约束的名称,可以在pgAdminIII中查找它(只需单击表名称并查看DDL,或者展开层次结构,直到看到“约束条件”),或者您可以查询信息架构 。
select * from information_schema.key_column_usage where position_in_unique_constraint is not null
用法:
select replace_foreign_key('user_rates_posts', 'post_id', 'ON DELETE CASCADE');
function:
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;
请注意:此function不会复制初始外键的属性。 它只需要外部表名/列名,丢弃当前键并replace新的键。