如何使用另一个表的插入触发器更新另一个表的值

时间:2019-06-21 11:50:12

标签: oracle plsql triggers

我正在从事有关全国选举制度的数据库项目。在为某个候选人投票时,我想自动在结果表中更新total_votes +1。所有候选人的total_votes始于零。我写了一个触发器,但是不起作用

/* I tried this trigger*/
    create or replace Trigger tvc
    after insert
    on cast_vote
Declare
for each row
begin
update results r
set total_vote = total_vote+1 
where :old.can_id=r.can_id;
end tvc ;



 /* This are the table's used */
    create table candidate(
    can_id number(8),
    name varchar(256),
    age number(3) check (age>=18),
    gender varchar(7),
    aff_party varchar(256),
    seat_no number(5),
    seat_name varchar(256),
    net_income number(8),
    primary key(can_id)
);

create table cast_vote(
    vote_no number(15) not null,
    voter_id number(8) not null unique,
    can_id number(8),
    primary key(vote_no),
    foreign key (voter_id) references voter(voter_id),
    foreign key(can_id) references candidate(can_id)
);

create table results (
    can_id number(10) primary key,
    total_vote number(10),
    foreign key (can_id) references candidate(can_id)
    );

/ 我希望触发器起作用 /

3 个答案:

答案 0 :(得分:0)

尝试一下,它应该可以工作

CREATE OR REPLACE TRIGGER tvc
AFTER INSERT ON cast_vote
REFERENCING NEW AS newRow OLD AS oldRow
FOR EACH ROW
BEGIN
UPDATE results SET total_vote =(select max(total_vote) from results where 
can_id=:newRow.can_id)+1 where 
can_id=:newRow.can_id;
END tvc;
  

编辑:

此外,如果RESULTS表中最初没有行,它将处理

CREATE OR REPLACE TRIGGER tvc
AFTER INSERT ON cast_vote
REFERENCING NEW AS newRow OLD AS oldRow
FOR EACH ROW
DECLARE
initialcnt number;
BEGIN
       SELECT COUNT(*) INTO initialcnt FROM results;
       IF(initialcnt=0) THEN
          INSERT INTO results VALUES(:newRow.can_id,1);
       ELSE
          UPDATE results SET total_vote =(select max(total_vote) from 
         results where can_id=:newRow.can_id)+1 where can_id=:newRow.can_id;
END tvc;

答案 1 :(得分:0)

最初,RESULTS表中没有行,因此没有要更新的内容;首先插入一行。

SQL> create table cast_vote(
  2      vote_no number(15) not null,
  3      voter_id number(8) not null unique,
  4      can_id number(8),
  5      primary key(vote_no)
  6  );

Table created.

SQL> create table results (
  2      can_id number(10) primary key,
  3      total_vote number(10)
  4      );

Table created.

SQL> create or replace Trigger tvc
  2    before insert on cast_vote
  3    for each row
  4  begin
  5    update results r set
  6      r.total_vote = r.total_vote + 1
  7      where r.can_id = :new.can_id;
  8
  9    if sql%rowcount = 0 then
 10       -- the first row for CAN_ID - insert
 11       insert into results (can_id, total_vote)
 12         values (:new.can_id, 1);
 13    end if;
 14  end tvc ;
 15  /

Trigger created.

测试:

SQL> insert into cast_vote (vote_no, voter_id, can_id) values (1000, 1, 200);

1 row created.

SQL> insert into cast_vote (vote_no, voter_id, can_id) values (1001, 2, 200);

1 row created.

SQL> select * From cast_Vote;

   VOTE_NO   VOTER_ID     CAN_ID
---------- ---------- ----------
      1000          1        200
      1001          2        200

SQL> select * From results;

    CAN_ID TOTAL_VOTE
---------- ----------
       200          2

SQL>

答案 2 :(得分:-1)

如果“所有候选人的总票数从零开始”意味着每个候选人都有一行,其票数最初定义为0,那么以下工作(几乎是您的工作):
1.删除声明,则不必要,也可以将其反转并“针对每一行”。
2.更改:old.can_id = r.can_id;到:new.can_id = r.can_id;在插入触发器中:old不存在(您可以引用它,但所有列均为空)。
如果总票数可能没有初始化,请使用合并。

create or replace Trigger tvc
    before insert
    on cast_vote
    for each row   
begin
  merge into results r
  using (select :new.can_id newid from dual) 
     on (newid = r.id)
   when matched then  
        update set total_vote = total_vote+1
   when not matched then 
        insert (id,total_vote) values(newid,1);
end tvc;