2014-09-22 88 views
2

我有一个来自以前的项目,我想在另一个项目中使用的数据库,从安全的原因,我需要更新其中一个表的ID。问题是,该表在很大程度上受外键从其他表引用:更新POSTGRESQL中的主键

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从table_photo参考行不通的ID。 我可能会使用这样的改变的ID:

UPDATE table_table SET id = id + 15613; 

我读的地方,我可以用ON UPDATE CASCADE约束这样做,但我不是很知道如何使用它。

btw:我正在使用Django ORM。

+0

对你有好处,包括表定义。谢谢。 – 2014-09-22 12:52:12

回答

3

获取约束名与\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约束。保留为空。
  • 向表B添加一个新列A_new_id,给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设置新的ID值相匹配。

  • 删除列B.A_id并将其重命名为B.A_new_idB.A_id
  • 删除列A.id和重命名A.new_idA.id
  • 创建自动之前创建的改名A.idUSING的指数PRIMARY KEY约束。

这很复杂,尤其是对于大表格,您通常希望分批执行这些步骤中的每一步。

如果这看起来太复杂了,就用上面的级联外键约束来做。

+1

我不得不将ADD和DROP约束分离到它自己的alter语句,但它工作。 – 2014-09-22 22:00:57