我想在删除学生时使用触发器/程序更新表'Teacher'中多列'student_total'的行 更新相关表中的多行,多对多的实现 'n'老师可以有'''学生
感谢Adv
Ritin
--------------- SQL
CREATE TABLE `Teacher` (
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`student_total` int(11) DEFAULT '0',
PRIMARY KEY (`id`)
);
CREATE TABLE `Student` (
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `Teacher_has_Student` (
`teacher_id` smallint(5) unsigned NOT NULL,
`student_id` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`teacher_id`,`student_id`),
KEY `fk_Teacher_has_Student_teacher` (`teacher_id`),
KEY `fk_breeder_has_breed_student` (`student_id`),
CONSTRAINT `fk_Teacher_has_Student_teacher` FOREIGN KEY (`teacher_id`) REFERENCES `Teacher` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_breeder_has_breed_student` FOREIGN KEY (`student_id`) REFERENCES `Student` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);
我有INSERT / DELETE / UPDATE的触发器 例如: ---------------------- SQL
CREATE TRIGGER teacher__student_insert AFTER INSERT ON Teacher_has_Student
FOR EACH ROW
BEGIN
UPDATE Teacher SET student_total = student_total + 1 WHERE id = NEW.teacher_id;
END;
下面的触发器只更新了1行,而目的是更新所有行。
DELIMITER |
CREATE TRIGGER my_student__delete AFTER DELETE ON Student
FOR EACH ROW
BEGIN
set @std_id = old.id;
UPDATE teacher SET student_total = student_total - 1
WHERE id = @std_id;
END
|
答案 0 :(得分:0)
我认为你的第二次触发没有意义。在删除学生时,您将使用他的id
并减少教师的student_total
,该教师意外地与学生一样id
。
您的定义加上第一个触发器应该已经完成了这项工作。如果您删除了某个学生,则Teacher_has_Student
会从CASCADE
删除他的关系,并且DELETE
您的触发器应该被触发以减少student_total
受影响的老师。无论如何谷歌的一项简短研究显示,MySQL显然不会触发级联删除触发器:
http://bugs.mysql.com/bug.php?id=13102
可能的解决方法
您可以尝试修复第二个触发器以手动完成工作:
DELIMITER |
CREATE TRIGGER my_student__delete AFTER DELETE ON Student
FOR EACH ROW
BEGIN
SET @std_id = old.`id`;
UPDATE
`Teacher` AS T
INNER JOIN `Teacher_has_Student` AS TS ON T.`id`=TS.`teacher_id`
SET `student_total` = `student_total` - 1
WHERE ST.`student_id` = @std_id;
END
|
但如果CASCADE
上的FOREIGN KEY
在触发前执行,那么这将无效。
可能更可靠的解决方法是放弃FOREIGN KEY
定义并在Teacher
和Student
上创建触发器,以将删除和更新级联到Teacher_has_Student
。
将其标准化
通过这些变通办法,您必须记住许多不同的方案,以保持student_total
有效。如果不一定要将student_total
直接存储在教师表中,我建议强烈不要这样做。
信息绝对是多余的。保留约束和级联,但删除student_total
列并删除所有触发器。然后使用JOIN获取学生编号:
SELECT
T.`id`, T.`name`, COUNT(*) AS student_total
FROM `Teacher` AS T
INNER JOIN `Teacher_has_Student` AS TS ON T.`id`=TS.`teacher_id`
GROUP BY T.`id`