为什么'从表中删除'忽略外键约束?

时间:2017-08-06 11:28:43

标签: mysql cascading-deletes

我有桌子:作者奖励(一对多关系)。我想制定下一条规则:

  • 奖励链接到author_id;
  • 如果具有author_id外键,则限制删除奖励;
  • 当我删除作者时,我想为此author_id的奖励表级联删除行。

我用过

constraint foreign key (author_id) 
references authors (author_id)
on delete cascade on update cascade

但无论如何我可以从奖励中删除行或所有行。如果我删除作者,我怎样才能从奖励中删除?

创建表格:

create table authors (
            author_id bigint not null auto_increment,
            birth_date datetime,
            first_name varchar(255),
            last_name varchar(255),
            sex varchar(10),
            primary key (author_id)
        );

create table rewards (
                reward_id bigint not null auto_increment,
                title varchar(255),
                year integer not null,
                author_id bigint not null,
                primary key (reward_id),
                constraint foreign key (author_id) references authors (author_id)
                on delete cascade on update cascade
                );

然后插入值:

    Insert into authors(
birth_date, first_name, last_name, sex) values
('1941-05-24', 'Bob', 'Dylan', 'male'),
('1870-10-22', 'Ivan', 'Bunin', 'male');

Insert into rewards(year, title, author_id) values 
(2016, 'Nobel Prize for Literature', 1),
(1933, 'Nobel Prize for Literature', 2),
(1903, 'Pushkin Prize', 2)
;

2 个答案:

答案 0 :(得分:0)

使用触发器足够简单,但您可能需要一个覆盖选项,可能基于另一个表。

drop trigger if exists delete_rewards;
delimiter $$

CREATE DEFINER=`root`@`localhost` TRIGGER `delete_rewards` BEFORE delete ON `rewards` 
FOR EACH ROW 
begin
    declare msg varchar(100);
    declare found int;
    set found = 0;
    select count(*) into found from authors a where a.author_id = old.author_id;

    if found > 0 then
        set msg = 'Delete Not allowed';
        signal sqlstate '45000' set message_text = msg;
    end if;


END $$

delimiter ;

答案 1 :(得分:0)

在制定约束时,您无法删除作者而不删除所有奖励。但您可以根据需要删除奖励。这是典型的一对多关系,其中一个是作者,而很多是奖励。这是有道理的,因为只要很多引用它,您就不想删除一个。 级联将起作用。

如果您想要防止操纵奖励记录,只要它们被分配,我就会推荐触发器和可能的历史记录表。

如果你想要一个奖励和许多作者,你必须扭转这种关系。所以作者必须参考他们的奖励。如果它是多对多,你将需要一个额外的表来处理这个问题。但是看到你的最后一个条件,我怀疑情况并非如此。