【问题标题】:How to delete records from parent table which is referenced by multiple child tables?如何从多个子表引用的父表中删除记录?
【发布时间】:2016-03-25 09:45:34
【问题描述】:

我有一个被多个表(大约 52 个)引用的表,此外,很少有子表有多个外键也引用其他表。

我想从父表中删除一条记录,我无法这样做,因为我收到错误“DELETE 语句与 REFERENCE 约束“FK_xxx”冲突。冲突发生在数据库“MyDB”,表“dbo”中.A",列'x'。"

我想要一个通用的 T-SQL 解决方案,它与表和引用数量无关。

【问题讨论】:

  • 请出示一些代码。也许我可以帮助你。

标签: sql sql-server tsql foreign-keys


【解决方案1】:

您必须查看“on delete”关键字,它是外键约束定义的一部分。 基本上你有 4 个选项:

  • NO ACTION(什么都不做)
  • CASCADE(同时删除孩子)
  • SET NULL(将引用字段设置为空)
  • SET DEFAULT(将引用字段设置为默认值)

一个例子是:

CREATE TABLE parent (
    id INT NOT NULL,
    PRIMARY KEY (id)
) ENGINE=INNODB;

CREATE TABLE child (
    id INT, 
    parent_id INT,
    INDEX par_ind (parent_id),
    FOREIGN KEY (parent_id) 
        REFERENCES parent(id)
        ON DELETE CASCADE -- replace CASCADE with your choice
) ENGINE=INNODB;

(对于这个例子和更多细节请看这里:http://dev.mysql.com/doc/refman/5.7/en/create-table-foreign-keys.html

如果你现在想修改你的约束,你首先必须删除它,然后创建一个新的,例如:

ALTER TABLE child 
ADD CONSTRAINT fk_name 
FOREIGN KEY (parent_id) 
REFERENCES parent(id) 
ON DELETE CASCADE; -- replace CASCADE with your choice

我希望这会有所帮助。还要提一下,您应该考虑可能不会真正删除您的父母,而是创建另一个布尔列“已删除”,如果有人单击删除,您将填写“是”。在“选择”查询中,然后按“已删除”列进行过滤。 优点是,您不会丢失此条目的历史记录。

【讨论】:

  • 不可能删除所有子表。我想要一个可以随时重复执行的代码或存储过程。
  • 我不确定您是否正确理解了这一点。您不删除表,您只删除外键约束并将其替换为您想要的行为。首先,您需要知道子表中的参考字段应该是什么样子。如果您对损坏的参考资料感到满意,请执行“无操作”。如果您还想在删除父级时删除子级,请选择“级联”,如果您想保留它以用于历史记录,您可以将其设置为“设置 NULL”,如果您想用不同的东西替换它,然后使用“默认设置”。您只会“丢失”引用而不是子数据
【解决方案2】:

您的问题是:FK 约束旨在防止您在 52 个表中的任何一个中创建孤立的子记录。我可以为您提供您寻求的脚本,但您必须首先意识到,当您尝试重新启用 FK 约束时,由于孤立数据(FK 约束旨在防止),约束将无法重新启用。对于您的下一步,无论如何都必须首先删除 52 个表中的每个表中的孤立数据。实际上,使用 ON DELETE CASCADE 重做约束要容易得多,或者放弃约束并完全忘记参照完整性。你不能同时拥有它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多