use*_*074 12 sql postgresql database-design referential-integrity foreign-keys
如果我定义表a
并b
如下:
CREATE TABLE a(i integer);
ALTER TABLE a ADD CONSTRAINT pkey_a PRIMARY KEY (i);
CREATE TABLE b(j integer);
ALTER TABLE b add CONSTRAINT fkey_ij FOREIGN KEY (j)
REFERENCES a (i) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE;
INSERT INTO a(i) VALUES(1);
Run Code Online (Sandbox Code Playgroud)
然后执行以下操作:
START TRANSACTION;
SET CONSTRAINTS ALL DEFERRED;
INSERT INTO b(j) VALUES(2);
INSERT INTO a(i) VALUES(2);
COMMIT;
Run Code Online (Sandbox Code Playgroud)
它产生以下错误.为什么SET CONSTRAINTS
没有达到预期的效果?
错误:表"b"上的插入或更新违反外键约束"fkey_ij"
SQL状态:23503详细信息:表"a"中不存在键(j)=(2).
Erw*_*ter 12
对于初学者来说,只能DEFERRABLE
推迟约束.
但是,这不会帮助你的情况,因为,FK约束不能这样弯曲可言.每个文件:
NO ACTION
即使约束被声明为可延迟,也不能推迟除检查之外的引用操作.
颠倒INSERT
语句的顺序.
有关:
我同意其他人的观点,即正确的方法是按正确的顺序 - 但有时这不是一个可行的选择,需要更简单的方法才能在时间预算内完成工作。
如果这对任何人有帮助,我制作了一个程序,可以自动将延迟选项添加到所有 FK,以便
将所有约束设置为推迟;
命令将会起作用。当然,仅在必要时使用它。
DO
$$
DECLARE
temp_rec RECORD;
sql_exe TEXT;
BEGIN
sql_exe := $sql$
ALTER TABLE %1$s ALTER CONSTRAINT %2$s DEFERRABLE;
$sql$
;
FOR temp_rec IN
(select constraint_name, table_name from information_schema.table_constraints where constraint_type = 'FOREIGN KEY')
LOOP
EXECUTE format(sql_exe, temp_rec.table_name, temp_rec.constraint_name);
END LOOP;
END;
$$
LANGUAGE plpgsql
;
Run Code Online (Sandbox Code Playgroud)