2012-01-14 24 views
0

生徒が削除されたときにトリガー/プロシージャを使用してテーブル '教師'の 'student_total'列の複数の行を更新したい 関連テーブルの複数行を更新する多対多の実数 「n」先生は「m」生徒を持つことができます関連テーブルの複数行の更新

  1. はまったく可能ですか?あなたのサイトから学んだ 結果セットを保存することができないので、
  2. Mysql、Postgressなどで?前売で

おかげ

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

私はあなたの第二のトリガーは意味がないと思います。学生の削除時に彼のidを取って先生のstudent_totalを減らします。これは偶然同じようにidと同じです。

あなたの定義と最初のトリガーはすでに仕事をしているはずです。生徒を削除するとTeacher_has_StudentからCASCADEで削除され、このDELETEのトリガーとなり、影響を受けた教師のstudent_totalが減少します。とにかく短い、Googleの研究が示すように、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 
| 

しかし、これは動作しません、FOREIGN KEYCASCADEはあなたのトリガの前に実行された場合。

たぶん、より信頼性の問題を回避するには、FOREIGN KEY定義をドロップするとTeacher_has_Studentに削除および更新をカスケード接続するTeacherStudentにトリガを作成することです。

ノーマライズそれはあなたが心の中でさまざまなシナリオの多くを維持する必要があります回避策で

student_totalが有効に維持します。教師用テーブルにstudent_totalを直接保管する必要がない場合は、しないことを強くお勧めします。

この情報は絶対的に冗長なものです。制約とカスケードは維持しますが、student_total列を削除し、すべてのトリガーを削除してください。あなたが行ったように、トピックをマークするための答えを受け入れることができ@ritin入力用

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` 
+0

おかげで...セカンドオピニオン、 あなたの説明は完璧な理にかなって、 敬礼 – ritin

+0

を望んでいた。その後、あなたの学生数を取得するために、JOINを使用。 – DerVO

+0

私はこの記事を見つけましたが、共有したかった http://wiki.postgresql.org/wiki/A_Brief_Real-world_Trigger_Example 私のウェブホストはトリガーをサポートしていませんでしたので、制約に固執する必要があります。 @Dervoもう一度ありがとう:) – ritin

関連する問題