我有一个以前项目的数据库,我想在另一个项目中使用,出于安全原因,我需要更新其中一个表的ID。问题是该表被其他表中的外键大量引用:
CREATE TABLE "table_table" (
"id" serial NOT NULL PRIMARY KEY,
"created" timestamp with time zone NOT NULL,
);
CREATE TABLE "table_photo" (
"id" serial NOT NULL PRIMARY KEY,
"table_id" integer NOT NULL REFERENCES "table_table" ("id") DEFERRABLE INITIALLY DEFERRED,
);
现在,如果我更改table_table上的id,则table_photo的引用将不起作用。 我可能会使用这样的东西来改变ID:
UPDATE table_table SET id = id + 15613;
我已经读过某些地方,我可以使用ON UPDATE CASCADE约束来做到这一点,但我不太清楚如何使用它。
btw:我正在使用Django ORM。
答案 0 :(得分:6)
使用\d "table_photo"
获取约束名称,其中显示:
Foreign-key constraints:
"table_photo_table_id_fkey" FOREIGN KEY (table_id) REFERENCES table_table(id) DEFERRABLE INITIALLY DEFERRED
然后用具有on update cascade
:
ALTER TABLE "table_photo"
DROP CONSTRAINT "table_photo_table_id_fkey",
ADD CONSTRAINT "table_photo_table_id_fkey"
FOREIGN KEY ("table_id")
REFERENCES "table_table"
ON UPDATE CASCADE
DEFERRABLE INITIALLY DEFERRED;
现在当您执行UPDATE
时,引用的行ID会自动更新。在"table_photo"."table_id"
上添加索引将有助于很多。
但是对于大桌来说这可能会很慢。如果你有大表,另一种选择是在几个阶段完成。对于表格A
,其中id
字段B
引用了A_id
字段new_id
A
约束向UNIQUE
添加新列A_new_id
。让它可以为空。B
添加新列A(new_id)
,为A.new_id
提供外键约束。UPDATE B
SET A_new_id = A.new_id
FROM A
WHERE B.A_id = A.id;
做一个
B.A_new_id
进行联接更新,在B.A_id
中设置新的ID值以匹配。
B.A_new_id
并将B.A_id
重命名为A.id
。A.new_id
并将A.id
重命名为PRIMARY KEY
A.id
上创建USING
约束,{{1}}之前自动创建的索引。它要复杂得多,特别是因为对于大表,你通常希望分批完成这些步骤。
如果这看起来太复杂,只需使用如上所述的级联外键约束。