使用ON DELETE两种方式,具有1-1关系,其中只有表具有外键

问题描述 投票:0回答:1

假设我有两张桌子,ab。表a包含FOREIGN KEY的可选b参考。表b没有FOREIGN KEY参考表a,不应该。这样做的原因是表a不是唯一可以从表b引用行的表:tables xy也可能引用b,将来可能会添加更多可能引用b行的表。

因此,表b中的每一行都只有一个“所有者行”,可能属于axy,或者可能属于其他许多表中的任何一个。

现在,如果删除表b中的一行,我希望它将axy中的外键引用设置为null,如果有的话,则为null。我知道我可以使用ON DELETE SET NULLa和其他表的外键约束中完成此操作,因此需要注意。

但是,如果删除“所有者行”,无论该行是否存在于axy等等,我都希望删除b中的相应行。这是我不知道该怎么办。

简而言之:

  1. a引用b。这是一个可选参考,并非所有as都有b。 (xy和其他表也与b有类似的关系)
  2. b不会也不应该参考a或其他任何表格。
  3. 如果我从a删除并且如果给定的a具有相应的b,则应删除b
  4. 如果我从b中删除,并且任何其他表包含对该b的引用,则引用应设置为null。

我怎么做到这一点?

mysql foreign-keys
1个回答
1
投票
create table a
( ...
, b_id  bigint default null comment 'fk ref b.id'
, constraint a_b_id foreign key (b_id) reference b (id) on delete set null 
, ...
) engine=innodb

xy的定义类似,可以使用可空的外键列

create table x 
( ...
, b_id  bigint default null comment 'fk ref b.id'
, constraint x_b_id foreign key (b_id) references b (id) on delete set null 
, ...
) engine=innodb

create table y 
( ...
, b_id  bigint default null comment 'fk ref b.id'
, constraint y_b_id foreign key (b_id) references b (id) on delete set null 
, ...
) engine=innodb

当从b删除一行时,三个表中任何一个表中的b_id列的任何值都引用已删除的行,这些值将更改为NULL。


MySQL中没有声明性约束可以完成3。

“如果我从a中删除并且如果给定的a具有相应的b,则应该删除该b。”

我们或许可以通过TRIGGER实现这一点,但是我们遇到了一些问题,哪些表可以被触发器中的语句引用。这可能最好用应用程序逻辑来处理,而不是数据库规则或触发器。

如果我要尝试触发,那么就像

 DELIMITER $$

 CREATE TRIGGER a_ad
 AFTER DELETE ON a
 FOR EACH ROW
 BEGIN
    DELETE FROM b WHERE b.id = OLD.b_id ;
 END$$

 DELIMITER ;

(我不确定这是否允许,或者是否会抛出错误......考虑一下

table b
---------
row id=42

table a
-------
row id=2  b_id=42
row id=3  b_id=42

考虑这个SQL语句

DELETE FROM a WHERE a.id IN (2,3);

id=2的删除将触发“删除后”触发器;并且将在b上执行DELETE,外键将找到行id=3引用,并尝试将b_id列设置为NULL ...但该行可能已被初始DELETE语句锁定...我只是不确定在这种情况下会发生什么;并且我们对触发器遇到了一些限制和限制(比如修改触发触发器的语句中引用的表中的行)

© www.soinside.com 2019 - 2024. All rights reserved.