使用外键约束来防止更新父行

时间:2015-09-18 16:10:19

标签: mysql

当子行使用索引时,是否可以使用外键约束来防止更新父行?

这是父表的架构:

create table if not exists incident_options (
id int  not null auto_increment primary key,
idx int not null,
field int not null , 
value varchar(50));

ALTER TABLE `incident_options` ADD unique (`idx`, field);

和子表:

create table if not exists incident_values (
optn int,
value varchar(1000));

ALTER TABLE `incident_values` ADD INDEX (`optn`);

这是我尝试过的约束:

ALTER TABLE `incident_values` 
ADD FOREIGN KEY (`optn`) REFERENCES `incident_options`(`id`) 
ON DELETE NO ACTION ON UPDATE RESTRICT;




假设我有以下数据:

incident_options
 __________________________
|id | idx  | field | value |    
| 1 |  0   |   1   | foo   |
| 2 |  1   |   1   | bar   |
 --------------------------

incident_values

 ______________
| optn | value |    
| 1    |  baz  |
 --------------



我想要达到的目的是防止' foo'因为该行在incident_values

中使用而被更新

更新' bar'会没事的

以下是我用来修改行的查询:

insert into incident_options (`idx`,`field`,`value`)
values ('0','1','test')
on duplicate key update
`idx` = values(`idx`),
`field` = values(`field`),
`value` = values(`value`)

目前' foo'将更新为' test'

2 个答案:

答案 0 :(得分:1)

问题是您已在错误的表格上设置约束。您已将ON UPDATE RESTRICT放在incident_values表上,但当您进行插入和更新时,这一切都发生在incident_options上。

不幸的是,你不能在incident_options表中设置这个约束,因为你可能并不总是有一个回到incident_values表的引用,所以我认为这不可能使用约束。正如Barmar在评论中提到的那样,您可以在更新字段之前以某种方式实施触发器以执行验证。

答案 1 :(得分:1)

有点hackery我实际上实现了我想要的。

强制增加' id'当'价值'已更改,更新了' id'如果有关系,将不被允许

on duplicate key update
idx = values(idx),
field = values(field),
id = if(
        values(`value`)=`value`,
        id,
        (SELECT Auto_increment FROM information_schema.tables WHERE table_name='incident_options')
        ),
values= values(value)

虽然在我的应用程序中实现它之前,我会看到是否有任何反对使用此解决方案的建议