gpt4 book ai didi

Oracle 复合触发器 - 如何存储和 "use"删除的行?索引表?

转载 作者:行者123 更新时间:2023-12-04 12:27:03 25 4
gpt4 key购买 nike

我现在正在为 Oracle 中的 DELETE 触发器进行长期的斗争,它在删除一行后,从剩余的行中选择一个新的 MAX 值并将其写入另一个表。在遇到恼人的 ORA-04091 变异表错误(在 FOR EACH ROW 中无法读取表)后,我切换到 Oracle 的复合触发器。

我怎样才能最好地存储已删除的行(每行有多个值,因为只有当删除的分数可能是高分而不是较低分数时,进一步的检查才会更新)?如果多个触发事件交火,我担心全局临时表可能会一团糟,例如为“DeletedMatches”运行的高分更新实际上并没有被删除,而是被 Before 触发事件注册。

我可以创建一个表吗a) 只存在于这个触发器的本地b) 可以像普通数据库表或临时表一样在 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;

最佳答案

“恼人的”变异表错误几乎总是表明设计不佳,通常是非规范化数据模型。这似乎适用于这种情况。在您需要维护聚合值、计数、最大值等时,为什么不使用 Oracle 的内置功能呢? Oracle 专门为我们提供了 MATERIALIZED VIEW 对象来处理摘要。 Find out more .

在您的情况下,将 CurrentHighScores 替换为物化 View 。

CREATE MATERIALIZED VIEW CurrentHighScores 
BUILD IMMEDIATE
REFRESH FAST
as select
(
Player ,
Game ,
max(score) as HighScore
from GameScores
group by player, game ;

您还需要在 GameScores 上构建一个 MATERIALIZED VIEW LOG。

关于Oracle 复合触发器 - 如何存储和 "use"删除的行?索引表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11259254/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com