触发器与级联的删除/更新

 

触发器不能用于执行级联更新和删除如果 ForeignKey 到字段名关系 (或 ForeignKey 到唯一的关系) 使用 SQL Server 的建立 DRI。 该 DRI 约束进行第一次测试 ; 如果更新或删除通过所有约束限制仅激发触发器。 因此,因为任何更新或需要进行层叠的删除将失败约束检查,DRI ForeignKey 约束不能存在上需要进行层叠这些关系。

通过不声明 ForeignKey (或引用) 约束,级联更新和删除可以实现使用触发器。 仍应使用字段名和唯一约束,但是。

删除触发器,在主表上的删除行在相关表中,或将所有相应 ForeignKeys 设置为 Null (或它们的默认值)。 级联删除轻松地执行嵌套触发器与每个删除相关表中的所有行。 濡傛灉杩欎簺鏇存柊必须层叠到相关表中的其他级别,级联 SetNull 和 SetDefault 可能是由于以多行的考虑事项与触发器问题多多。 然而,在 ForeignKeys 不也是相关表的字段名的一部分,如果它们可以只需更新从触发器内。

用于实现已级联的更新,在主表上的一个更新触发器应执行辅助表中的所需的数据修改。 再次,只要正在更新 ForeignKey 不是依赖于表的字段名的一部分,它只是由更新触发器内。

提供与 SQL Server 4.2 x 提供的示例在文档更新和删除实施了参照完整性的触发器。 所附的 SQL Server 的触发器文档描述用于业务规则强制执行,而不是参照完整性的触发器,但如何触发器工时和 Multirow 注意事项上的信息是信息性的 (请参阅该 SQL Server"数据库开发人员助理"第 6 章)。

下面是一个示例的一个级联删除 titles 表中删除具有匹配 ForeignKey 值 titleauthor 表中的所有行上的触发器。 因为 title_id 是 titleauthor 的字段名的一部分,此触发器将假定有没有后续级别的具有 ForeignKeys titleauthor 引用的表。 请注意这将正常运行甚至作为关于多行删除操作。

CREATE TRIGGER DelCascadeTrig
  ON titles
  FOR DELETE
AS
  DELETE titleauthor
    FROM titleauthor, deleted
    WHERE titleauthor.title_id = deleted.title_id
				


下面是一个 SetNull 的示例删除更新 titleauthor 表中的所有行具有匹配的外键值 titleauthor 表上的触发器。 再次,因为 title_id 是 titleauthor 的字段名的一部分,此触发器将假定有没有后续级别的具有 ForeignKeys titleauthor 引用的表。 这将甚至作为关于多行删除操作正确工作。

CREATE TRIGGER DelSetNullTrig
  ON titles
  FOR DELETE
AS
    UPDATE titleauthor
      SET titleauthor.title_id = NULL
        FROM titleauthor, deleted
        WHERE titleauthor.title_id = deleted.title_id
				


以下是级联更新触发器在 titles 表中具有匹配的外键值更新 titleauthor 表中的所有行上的一个示例。 再次,因为 title_id 是 titleauthor 的字段名的一部分,此触发器将假定有没有后续级别的具有 ForeignKeys titleauthor 引用的表。

CREATE TRIGGER UpdCascadeTrigBad
  ON titles
  FOR UPDATE
AS
  IF UPDATE(title_id)
  BEGIN
    UPDATE titleauthor
      SET titleauthor.title_id = inserted.title_id
        FROM titleauthor, deleted, inserted
        WHERE titleauthor.title_id = deleted.title_id
    END
  END
				


这将不能正常工作的多行更新因为没有要匹配其对应的行插入表中与已删除的表中给定的行而不添加第二个的唯一标识符永远不会更改其值的方法。 这是当在级联需要采取后续级别在 ForeignKey 依赖的表中字段名的一部分,并且依赖于表格中的字段名由其他 ForeignKeys 引用时,出现同样的问题。

若要防止关于多行更新,前面触发器应将重写要防止更新影响多个行的原始表 (标题在这种情况下)。 注意在触发器中的更新可能嗯更新 titleauthor 中的多个行 ; 此解决方案以多行的问题可能只是导致问题重新出现在层叠中下一级别。

CREATE TRIGGER UpdCascadeTrig
  ON titles
  FOR UPDATE
AS
  IF UPDATE(title_id)
  BEGIN
    IF @@ROWCOUNT = 1
      UPDATE titleauthor
        SET titleauthor.title_id = inserted.title_id
          FROM titleauthor, deleted, inserted
          WHERE titleauthor.title_id = deleted.title_id
    ELSE
      ROLLBACK TRANSACTION
      RAISERROR ('Multi-row update on table "titles" not allowed.')
    END
  END
				

 

你可能感兴趣的:(触发器与级联的删除/更新)