如何添加触发器以查找电影数据库中每部电影的平均,总和和评级数

问题描述 投票:0回答:2

我必须添加电影的收视率的平均值和总数!以下是我的餐桌和老虎!请改进此代码!

create table fanrating
  (
   mov_id number(10),
   rate_avg number(1,1),
   rate_sum number,
   rate_count number
   );    
create table rating 
   ( 
    mov_id number(10) references movie(mov_id),
    userid varchar(20),
    rev_star number,
    primary key(mov_id,rev_star)
    );

delimiter $$
create or replace trigger bi_rating_trg
  before insert on fanrating
  for each row
begin
  set rate_sum = 0;
  set rate_count = 0;
  set rate_avg = null;
end;
$$
create or replace trigger ai_rating_trg
  after insert on rating
  for each row
begin
  update fanrating
     set rate_sum   = rate_sum + new.rev_star,
         rate_count = rate_count + 1,
         rate_avg   = rate_sum / rate_count
   where mov_id = new.mov_id;
end;
$$ delimiter;  

它在触发器的所有3个set命令中都显示错误,并且还遇到称为符号$$的错误,我正在使用Oracle SQL Delevepor!

oracle plsql oracle11g database-trigger
2个回答
1
投票

一些反对意见:

  • 您不需要第一个(插入之前)触发器
  • [newold值前应加冒号,即:new:old
  • 在PL / SQL中没有set命令(至少,我对此一无所知)。如果要设置某个变量为某个值,可以将其设置为my_variable := :new.rate_star;
  • 我从未使用过delimiter;不知道你打算怎么做。标准分隔符为分号和斜杠,建议您使用它们]

这就是我要做你想做的事情。

先上桌:

SQL> create table fanrating
  2    (mov_id     number(10),
  3     rate_avg   number,
  4     rate_sum   number,
  5     rate_count number
  6    );

Table created.

SQL> create table rating
  2     (mov_id    number(10),
  3      userid    varchar(20),
  4      rev_star  number,
  5      primary key(mov_id,rev_star)
  6     );

Table created.

触发器使用merge命令,也称为“ upsert”,因为它执行的是update(如果有匹配项,我该怎么做)或insert(如果没有):]]

SQL> create or replace trigger ai_rating_trg
  2    after insert on rating
  3    for each row
  4  begin
  5    merge into fanrating f
  6      using (select :new.rev_star rev_star,
  7                    :new.mov_id   mov_id
  8             from dual
  9            ) x
 10      on (f.mov_id = x.mov_id)
 11    when matched then update set
 12      f.rate_sum = f.rate_sum + :new.rev_star,
 13      f.rate_count = f.rate_count + 1,
 14      f.rate_avg = round((f.rate_sum + :new.rev_star) /
 15                         (f.rate_count + 1), 2)
 16    when not matched then insert values
 17      (:new.mov_id, :new.rev_star, :new.rev_star, 1);
 18  end;
 19  /

Trigger created.

测试:

SQL> insert into rating (mov_id, userid, rev_star) values (1, 'Little', 3);

1 row created.

SQL> select * From fanrating;

    MOV_ID   RATE_AVG   RATE_SUM RATE_COUNT
---------- ---------- ---------- ----------
         1          3          3          1

SQL> insert into rating (mov_id, userid, rev_star) values (1, 'Foot', 1);

1 row created.

SQL> select * From fanrating;

    MOV_ID   RATE_AVG   RATE_SUM RATE_COUNT
---------- ---------- ---------- ----------
         1          2          4          2

SQL> insert into rating (mov_id, userid, rev_star) values (1, 'Scott', 4);

1 row created.

SQL> select * From fanrating;

    MOV_ID   RATE_AVG   RATE_SUM RATE_COUNT
---------- ---------- ---------- ----------
         1       2,67          8          3

SQL> insert into rating (mov_id, userid, rev_star) values (2, 'Foot', 5);

1 row created.

SQL> select * From fanrating;

    MOV_ID   RATE_AVG   RATE_SUM RATE_COUNT
---------- ---------- ---------- ----------
         1       2,67          8          3
         2          5          5          1

SQL>

[编辑:过程+触发器]

如果必须是一个过程,那么-正如我评论的那样-将MERGE移入其中,请使用插入的值作为参数。方法如下:

步骤:

SQL> create or replace procedure p_mrg
  2    (par_mov_id   in number,
  3     par_userid   in varchar2,
  4     par_rev_star in number
  5    )
  6  as
  7  begin
  8    merge into fanrating f
  9      using (select par_rev_star rev_star,
 10                    par_mov_id   mov_id
 11             from dual
 12            ) x
 13      on (f.mov_id = x.mov_id)
 14    when matched then update set
 15      f.rate_sum = f.rate_sum + par_rev_star,
 16      f.rate_count = f.rate_count + 1,
 17      f.rate_avg = round((f.rate_sum + par_rev_star) /
 18                         (f.rate_count + 1), 2)
 19    when not matched then insert values
 20      (par_mov_id, par_rev_star, par_rev_star, 1);
 21  end;
 22  /

Procedure created.

触发器现在调用过程(而不是运行MERGE本身:]]

SQL> create or replace trigger ai_rating_trg
  2    after insert on rating
  3    for each row
  4  begin
  5    p_mrg (:new.mov_id, :new.userid, :new.rev_star);
  6  end;
  7  /

Trigger created.

附加测试:

SQL> insert into rating (mov_id, userid, rev_star) values (2, 'Mike', 2);

1 row created.

SQL> select * from fanrating;

    MOV_ID   RATE_AVG   RATE_SUM RATE_COUNT
---------- ---------- ---------- ----------
         1       2,67          8          3
         2        3,5          7          2

SQL> 

您不需要为fanrating表创建这样的触发器,但是需要在创建过程中定义默认值,例如:

create table fanrating
  (
   mov_id     number(10),
   rate_avg   number(1,1),
   rate_sum   number default 0,
   rate_count number default 0
   );

并为insert or update表创建rating触发器:

create or replace trigger ai_rating_trg 
after insert or update on rating
  for each row
begin 
update fanrating 
   set rate_sum = nvl(rate_sum,0) + nvl(:new.rev_star,0),
       rate_count = nvl(rate_count,0) + 1,
       rate_avg = nvl(rate_sum,0) / nvl(rate_count,1)
 where mov_id = :new.mov_id;
end;
/

其中nvl(..,0)用于将null值转换为zero


1
投票

您不需要为fanrating表创建这样的触发器,但是需要在创建过程中定义默认值,例如:

© www.soinside.com 2019 - 2024. All rights reserved.