首页 文章

何时使用“ON UPDATE CASCADE”

提问于
浏览
371

我经常使用“ON DELETE CASCADE”,但我从不使用“ON UPDATE CASCADE”,因为我不太确定在什么情况下它会有用 .

为了便于讨论,请看一些代码 .

CREATE TABLE parent (
    id INT NOT NULL AUTO_INCREMENT,
    PRIMARY KEY (id)
);

CREATE TABLE child (
    id INT NOT NULL AUTO_INCREMENT, parent_id INT,
    INDEX par_ind (parent_id),
    FOREIGN KEY (parent_id)
        REFERENCES parent(id)
        ON DELETE CASCADE
);

对于"ON DELETE CASCADE",如果删除了具有 id 的父级,则将自动删除具有 parent_id = parent.id 的子级中的记录 . 这应该没问题 .

  • 这意味着当父级的 id 更新时,"ON UPDATE CASCADE"会做同样的事情吗?

  • 如果(1)为真,则表示如果 parent.id 不可更新(或永远不会更新),则无需使用"ON UPDATE CASCADE",如 AUTO_INCREMENT 或始终设置为 TIMESTAMP . 是对的吗?

  • 如果(2)不成立,在其他什么样的情况下我们应该使用“ON UPDATE CASCADE”?

  • 如果我(出于某种原因)将 child.parent_id 更新为不存在的内容,会自动删除吗?

好吧,我知道,上面的一些问题可以通过程序测试来理解,但我也想知道这是否依赖于数据库供应商 .

请说清楚 .

6 回答

  • 3

    几天前我've had an issue with triggers, and I'已经发现 ON UPDATE CASCADE 可能有用 . 看看这个例子(PostgreSQL):

    CREATE TABLE club
    (
        key SERIAL PRIMARY KEY,
        name TEXT UNIQUE
    );
    
    CREATE TABLE band
    (
        key SERIAL PRIMARY KEY,
        name TEXT UNIQUE
    );
    
    CREATE TABLE concert
    (
        key SERIAL PRIMARY KEY,
        club_name TEXT REFERENCES club(name) ON UPDATE CASCADE,
        band_name TEXT REFERENCES band(name) ON UPDATE CASCADE,
        concert_date DATE
    );
    

    在我的问题中,我必须定义一些额外的操作(触发器)来更新Concert的表 . 这些操作必须修改club_name和band_name . 由于参考,我无法做到这一点 . 我无法修改音乐会,然后处理俱乐部和乐队表 . 我也不能这样做 . ON UPDATE CASCADE 是解决问题的关键 .

  • 4

    我的评论主要是参考第3点:如果我们假设父键不可更新,在什么情况下ON UPDATE CASCADE适用?这是一个案例 .

    我正在处理一个复制场景,其中需要将多个卫星数据库与主站合并 . 每个卫星都在相同的表上生成数据,因此将表合并到主站会导致违反唯一性约束 . 我正在尝试使用ON UPDATE CASCADE作为解决方案的一部分,我在每次合并期间重新增加密钥 . ON UPDATE CASCADE应通过自动化部分过程来简化此过程 .

  • 14

    确实,如果您的主键只是一个自动递增的标识值,那么您将无法真正使用ON UPDATE CASCADE .

    但是,假设您的主键是10位UPC条形码,并且由于扩展,您需要将其更改为13位UPC条形码 . 在这种情况下,ON UPDATE CASCADE将允许您更改主键值,并且具有该值的外键引用的任何表将相应地更改 .

    在参考#4时,如果将子ID更改为父表中不存在的内容(并且您具有参照完整性),则应该获得外键错误 .

  • 417
    • 是的,这意味着,例如,如果你做 UPDATE parent SET id = 20 WHERE id = 10 所有孩子,parent_id的10也将更新为20

    • 如果不更新外键引用的字段,则不需要此设置

    • 想不出任何其他用途 .

    • 由于外键约束失败,您无法执行此操作 .

  • 75

    我认为你几乎已经指出了这一点!

    如果您遵循数据库设计最佳实践,并且您的主键永远不可更新(我认为应该始终如此),那么您永远不需要 ON UPDATE CASCADE 子句 .

    Zed 提出了一个很好的观点,如果您使用 natural 键(例如数据库表中的常规字段)作为主键,则可能会出现需要更新主键的某些情况 . 另一个最近的例子是ISBN(国际标准书号),它不久前从10到13位字符变化 .

    如果您选择使用 surrogate (例如人工系统生成的)密钥作为您的主键(除了最罕见的情况之外,这将是我的首选),情况并非如此 .

    所以最后:如果您的主键永远不会改变,那么您永远不需要 ON UPDATE CASCADE 子句 .

  • 26

    这是一个很好的问题,我昨天也有同样的问题 . 我想到了这个问题,特别是如果存在类似“ON UPDATE CASCADE”的东西,那么很幸运,SQL的设计者也考虑过这个问题 . 我同意Ted.strauss,我也评论了Noran的案子 .

    我什么时候用的?就像Ted指出的那样,当你一次处理几个数据库,并在一个数据库中进行修改时在一张 table 中,它们在Ted所谓的“卫星数据库”中有任何形式的复制,不能用原始ID保存,并且出于任何原因你必须创建一个新的,以防你不能更新旧数据(例如由于权限,或者如果您在如此短暂的情况下搜索坚固性,而不是绝对和完全尊重规范化的总规则,则仅仅因为将是一个非常短命的实用程序)

    所以,我同意两点:

    (A.)是的,很多时候更好的设计可以避免它;但

    (B.)在迁移,复制数据库或解决紧急情况的情况下,这是一个伟大的工具,幸运的是,当我去搜索它是否存在时 .

相关问题