更新POSTGRESQL中的主键

时间:2014-09-22 11:58:15

标签: sql database postgresql

我有一个以前项目的数据库,我想在另一个项目中使用,出于安全原因,我需要更新其中一个表的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。

1 个答案:

答案 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}}之前自动创建的索引。

它要复杂得多,特别是因为对于大表,你通常希望分批完成这些步骤。

如果这看起来太复杂,只需使用如上所述的级联外键约束。