テーブルに重複を挿入できる場合、テーブルの設計が間違っています。それが起こらないことを保証する一意の制約が必要です。
何らかの理由でテーブルを修正できないと仮定すると、次のようになります。
CREATE TRIGGER ins_table1
INSERT ON table1 REFERENCING NEW AS new
FOR EACH ROW (EXECUTE PROCEDURE ins_table1(new.a, new.b, new.c));
これは、行を一意に識別するには列と列a
で十分であるb
と想定しています。c
トリガーと手順の名前を変更して、関連する内容とタイミングをより正確に反映させました。del
on と呼ばれるものの接頭辞としてはあまり適切ではありませんINSERT
。
CREATE PROCEDURE ins_table1(new_a INTEGER, new_b INTEGER, new_c INTEGER)
DEFINE l_a LIKE table1.a;
FOREACH SELECT a INTO l_a
FROM table1
WHERE a = new_a AND b = new_b AND c = new_c
RAISE EXCEPTION -271, -100;
END FOREACH;
END PROCEDURE;
これは、挿入される行ごとに呼び出されます。SELECT ステートメントが行を返す場合、FOREACH ループの本体に入るため、例外が発生し、INSERT は多かれ少なかれ適切なエラー (-271 Could not insert new row into the table; - 100 ISAM エラー: 一意のキーを持つレコードの値が重複しています)。
AFTER トリガーを使用してこの検証を実行しようとすると、挿入された単一のキーの組み合わせだけをターゲットにするのではなく、テーブル全体をスキャンして重複がないかどうかを確認する必要があります。一般に、INSERT は複数の行を持つことができることに注意してください (考えてみてくださいINSERT INTO Table SELECT * FROM SomeWhereElse
)。パフォーマンスの違いは劇的です!(AFTER トリガーのクエリは、次のようにする必要がありますSELECT a, b, c FROM table1 GROUP BY a, b, c HAVING COUNT(*) > 1
。)