私は、行を削除すると、残りの行から新しい MAX 値を選択し、それを別のテーブルに書き込む Oracle の DELETE トリガーを求めて、長い間闘っています。面倒な ORA-04091 mutating table エラー (FOR EACH ROW ではテーブルを読み取れない) に出くわした後、Oracle の複合トリガーに切り替えました。
削除された行を最適に保存するにはどうすればよいですか (行ごとに複数の値。それ以降のチェックでは、削除されたスコアが低いスコアではなく、高いスコアであった可能性がある場合にのみ更新されるため)。複数のトリガーイベントがクロスファイアし、たとえば、実際には削除されていないが、Before トリガーイベントによって登録された「DeletedMatches」に対してハイスコアの更新が実行されると、グローバル一時テーブルが混乱して終了する可能性があるのではないかと心配しています。
a) このトリガーでローカルにのみ存在する b) 通常の DB テーブルや一時テーブルのように SQL で使用できるテーブルを作成できますか?
次の (疑似) コードは、一致が削除されるたびに CurrentHighScores テーブルを更新します (古いハイスコアは消え、残りの最高スコアに置き換えられます)。
CREATE TABLE GameScores (
MatchId number not null --primary key
Player varchar(255) not null,
Game varchar(255) not null, -- PacMan, Pong, whatever...
Score number not null );
-- High score for each game:
CREATE TABLE CurrentHighScores (
HiScId number not null --primary key
Player varchar(255) not null,
Game varchar(255) not null,
HighScore number not null );
create or replace TRIGGER UpdHiScoreOnMatchDelete
FOR DELETE ON GameScores
COMPOUND TRIGGER
TYPE matchtable IS TABLE OF GameScores%ROWTYPE INDEX BY SIMPLE_INTEGER;
DeletedMatches matchtable;
MatchIndex SIMPLE_INTEGER := 0;
BEFORE EACH ROW IS -- collect deleted match scores
BEGIN
MatchIndex:= MatchIndex+ 1;
DeletedMatches(MatchIndex).Game := :old.Game;
DeletedMatches(MatchIndex).Score := :old.Score;
-- don't want to set every column value, want to
-- do like: INSERT :old INTO DeletedMatches;
-- don't want the Index either!
END BEFORE EACH ROW;
AFTER STATEMENT IS
BEGIN
UPDATE CurrentHighScores hsc
SET hsc.HighScore=(
select max(gsc.Score) from GameScores gsc
where hsc.Game=gsc.Game)
where hsc.Game IN (
select del.Game from DeletedMatches del where hsc.HighScore = del.Score)
-- won't work, how can I check within the SQL if a row
-- for this game has been deleted, or anyhow integrate
-- DeletedMatches into the SQL, without a cursor?
-- Optional further cond. in subselect, to update only
-- if deleted score equals highscore:
and exists(
select 1 from GameScores where Game=hsc.Game);
-- ignore games without remaining match scores.
-- Delete/set zero code for games without existing scores omitted here.
END AFTER STATEMENT;