【问题标题】:Does the foreign keys automatically get updated as primary table is updated?主表更新时外键是否会自动更新?
【发布时间】:2013-10-26 17:24:22
【问题描述】:

以上是我的简单数据库设计,只是想了解事情是如何发生的,因为我是数据库的新手。以下是我的问题:

  1. 当我更新walls 表中的wall_id 时,wall_categories 表中的wall_id 是否也会更新?作为wall_id wall_categories 表引用墙壁表中的 wall_id。

  2. 与 wall 表中的 desktop_id 相同,因为它是引用 desktop_wall 表中的 desktop_id 的外键,所以当我更新时 墙表中的 desktop_id 也执行deskotp_wall 中的desktop_id 更新了吗?

  3. 如果默认不更新,怎么办?

非常感谢!

【问题讨论】:

  • 好吧,最好一开始不更新主键...
  • @marc_s,你能详细说明一下吗?为什么不呢?还有什么另一种选择?谢谢!

标签: sql-server database foreign-keys primary-key rdbms


【解决方案1】:

此功能称为级联参照完整性。当您定义外键约束时,它是可选的。此处描述了启用它的语法(Micorosoft SQL,但语法是标准的,并且大多数 DBMS 都支持它):

http://technet.microsoft.com/en-us/library/ms186973(v=sql.105).aspx

【讨论】:

    【解决方案2】:

    在postgresql中我是这样写的

    ALTER TABLE a_table
    ADD CONSTRAINT fk_a_b FOREIGN KEY (a_id)
    REFERENCES b_table (b_some_id) 
    ON DELETE CASCADE ON UPDATE CASCADE;
    

    并以级联方式更新和删除文件。

    【讨论】:

      【解决方案3】:

      不,外键不会自动更新。您需要更新自己引用的表中的外键,否则会导致引用完整性异常。

      要自动更新外键,您可以使用 TRIGGERS。

      编辑:-

      根据 cmets 中的 sqlvogel 的建议,如果您的 DBMS 支持级联更新,则您无需为此创建 TRIGGERS。

      在这种情况下,如果你有Cascading Referential Integrity Constraints会更好

      通过使用级联参照完整性约束,您可以定义 当用户尝试删除或删除 SQL Server 时执行的操作 更新现有外键指向的键。

      【讨论】:

      • 是那些 ON UPATE、ON DELETE 触发器吗? *哦,我认为这些是限制。
      • 您可以在列上创建触发器,以便自动更新外键。因此,每当更改列时,外键都会自动更新!
      • 其实如果你有一个没有ON UPDATE CASCADE的外键,那么就不能先更新parent,也不能先更新child。两者都会导致冲突。除非你的数据库支持延迟约束检查。
      • @sqlvogel:- 是的,这是正确的,但由于 OP 没有提及它,所以我只是提供了一个替代方案
      • @BillKarwin:- 我没有得到太多。如果我遗漏了什么,你能告诉我吗?提前致谢
      【解决方案4】:
      1. 当我更新walls 表中的wall_id 时,wall_categories 表中的wall_id 是否也会更新?作为wall_categories 表中的wall_id 引用了walls 表中的wall_id。

      2. 与 wall 表中的 desktop_id 相同,因为它是引用 desktop_wall 表中的 desktop_id 的外键,所以当我更新 wall 表中的 desktop_id 时,deskotp_wall 中的 desktop_id 是否也会更新?

      不,更新不会自动发生。事实上,您会收到SQLException,因为您试图破坏参照完整性,因此您的更新会失败。这假设您已将有效的Constraints 应用于表。


      还有一个ON UPDATE CASCADE,但它不在所有数据库上都受支持。虽然,级联更新显然应该是首选;如果您的数据库不支持它,您需要实现 after-row Trigger。

      例如,在Oracle 中,您可以这样实现:

      CREATE OR REPLACE TRIGGER walls_wall_upd_trg
       AFTER UPDATE OF wall_id ON walls FOR EACH ROW
      BEGIN
          UPDATE wall_categories
             SET wall_id = :new.wall_id
           WHERE wall_id = :old.wall_id;
      
          UPDATE wall_comments
             SET wall_id = :new.wall_id
           WHERE wall_id = :old.wall_id;
      END;
      
      CREATE OR REPLACE TRIGGER walls_desk_upd_trg
       AFTER UPDATE OF desktop_id ON walls FOR EACH ROW
      BEGIN
          UPDATE desktop_wall
             SET desktop_id = :new.desktop_id
           WHERE desktop_id = :old.desktop_id;
      END;
      

      【讨论】:

      • 我不确定这是真的。 ON DELETE CASCADE 只能在 DELETE 命令上执行,如果更改 ID,可能会出现异常但无法删除记录。
      • 还有一个ON UPDATE CASCADE,但并非所有数据库都支持它。你的目标数据库是什么?
      • @baltov 你是对的。似乎大多数数据库在更新时都失败了。感谢您指出这一点。
      猜你喜欢
      • 2019-06-22
      • 1970-01-01
      • 1970-01-01
      • 2014-11-28
      • 2016-04-02
      • 2015-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多