【问题标题】:Mutating table - trigger error变异表 - 触发错误
【发布时间】:2016-04-20 05:27:42
【问题描述】:

我必须实现以下触发器:

1960 年之后的选举,每个选举年的总票数不超过 538

但是,我得到了变异表错误。我明白为什么我会收到错误消息,但我看不到其他解决方案(带触发器)。我可以创建一个临时表,但我只想拥有触发器。 代码如下:

 CREATE OR REPLACE TRIGGER restrict_election_votes
 after INSERT OR UPDATE ON election
 for each row
 declare 
v_nbofvotes number;
v_eleyr election.election_year%type :=:NEW.election_year;
v_votes election.votes%type :=:NEW.VOTES;

begin 
select sum(votes)
into v_nbofvotes
from election
where election_year=v_eleyr;

if(v_votes+v_nbofvotes >538) 
THEN
    RAISE_APPLICATION_ERROR(-20500, 'Too many votes');
  END IF;

END;


update election
set votes=175
where candidate='MCCAIN J'
and election_year=2008;

【问题讨论】:

  • 如果您删除“for each row”并使其成为语句级触发器(将不得不更改查询以检查自 1960 年以来所有选举的 sum(votes) 规则,因为您不知道插入/更新了哪一行)那么它应该可以工作。
  • 我认为这里的问题不是“每一行”而是从自身中选择。只需删除 select 语句,我认为您实际上并不需要它:您只需要检查 :NEW.VOTES 。
  • CREATE OR REPLACE TRIGGER restrict_election_votes before INSERT OR UPDATE ON election declare v_nbofvotes number; begin select sum(votes) into v_nbofvotes from election where election_year>1960; if(v_nbofvotes >(538 *((extract( year from sysdate))-1960))) THEN RAISE_APPLICATION_ERROR(-20500, 'Too many votes'); END IF; END; 还是不行
  • @stee1rat - 我的印象是,限制是选举的总票数,而不是候选人,这意味着必须查询选举中的所有候选人。]
  • @MonicaS - 我将其充实到下面的答案中以证明我的意思。

标签: sql oracle plsql triggers mutating-table


【解决方案1】:

假设问题是您需要查询选举表,因为投票总数是由多行确定的,那么如果您删除“for each row”并使其成为语句级触发器(将不得不更改查询以检查自 1960 年以来所有选举的 sum(votes) 规则,因为您不知道插入/更新了哪一行)然后它将起作用。

create table mb_elct (year varchar2(4), cand varchar2(30), vt number)

create or replace trigger mb_elct_trg
after insert or update on mb_elct
declare 
   v_nbofvotes number;
begin
select count(*) 
into  v_nbofvotes
from (
  select year, sum(vt)
    from mb_elct
  where  year > '1960'
  group by year
  having sum(vt) >538
);

if(nvl(v_nbofvotes,0) != 0 ) 
THEN
    RAISE_APPLICATION_ERROR(-20500, 'Too many votes');
  END IF;

END;
/

insert into mb_elct values ('2008', 'McCain', 500);

1 row inserted

update mb_elct set vt = vt + 200 where year = '2008' and cand = 'McCain';
ORA-20500: Too many votes
ORA-06512: at "EDR_ADMIN.MB_ELCT_TRG", line 16
ORA-04088: error during execution of trigger 'EDR_ADMIN.MB_ELCT_TRG'

【讨论】:

    【解决方案2】:

    你确定你需要一个触发器吗?你可以用check constraint解决这个问题:

    alter table election add consntraint too_many_votes check (votes < 538 or year < 1960);
    

    【讨论】:

    • 很好的解决方案,但请确保不要忘记“1960 年代之后”限定词
    • 基于触发器中的查询,似乎 OP 需要对多行的投票求和,在这种情况下这将不起作用,但不知道数据的粒度我不能说当然..
    • @DanK,谢谢!改了。
    猜你喜欢
    • 2018-02-19
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 2019-02-19
    • 2018-07-26
    • 2013-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多