触发器一直无法编译。当 table 存在时找不到声明 table
Trigger keeps failing to compile. Claims table not found when table exists
所有被调用的table肯定存在。我也仔细检查了拼写。
sqldeveloper 给出的错误不是很有帮助,我似乎无法弄清楚为什么会失败。我正在尝试创建一个触发器,在收到新评论时更新 top5restaurants table。我有一个程序可以解析评论并将它们添加到评级 table。 top5restaurant table 保留了评分最高的 5 家餐厅。
drop view bestratings_rest;
create view bestratings_rest(rid, rate) as
(select distinct rid, max(stars) from rating
group by rid);
drop table top5restaurants;
create table top5restaurants(rid int);
insert into top5restaurants rid
select rid from
(select rid, rate from bestratings_rest r
order by r.rate asc)
where rownum <=5;
drop view top5rest;
create view top5rest as
select rid, best from(
select t.rid, best from top5restaurants t
inner join (select distinct rid, max(stars) as best from rating
group by rid) b
on t.rid = b.rid);
create or replace trigger top5_trigger
after insert on rating
for each row
declare
minrow top5rest%rowtype;
restrid restaurant.rid%type;
restname restaurant.name%type;
begin
insert into minrow
select rid, min(best) from top5rest;
insert into restname
select rid from restaurant
where :new.rid = restaurant.rid;
if :new.stars > minrow.best then
DELETE FROM top5restaurants
where top5restaurants.rid = :new.rid;
insert into top5restaurants values(rid);
end if;
end;
/
--
--
begin
update_reviews('Jade Court','Sarah M.', 4, '08/17/2017');
update_reviews('Shanghai Terrace','Cameron J.', 5, '08/17/2017');
update_reviews('Rangoli','Vivek T.',5,'09/17/2017');
update_reviews('Shanghai Inn','Audrey M.',2,'07/08/2017');
update_reviews('Cumin','Cameron J.', 2, '09/17/2017');
end;
/
select * from top5restaurants;
sqldeveloper 输出:
视图 BESTRATINGS_REST 已删除。
视图 BESTRATINGS_REST 已创建。
Table 排名前 5 的餐厅下降。
Table 创建了 TOP5 餐厅。
已插入 5 行。
查看 TOP5REST 已删除。
查看已创建的 TOP5REST。
触发TOP5_TRIGGER编译
LINE/COL错误
7/5 PL/SQL: SQL 语句被忽略
7/17 PL/SQL: ORA-00942: table 或视图不存在
11/5 PL/SQL:SQL 语句被忽略
11/17 PL/SQL: ORA-00942: table 或视图不存在
18/5 PL/SQL:SQL 语句被忽略
18/40 PL/SQL: ORA-00984: 此处不允许列
错误:检查编译器日志
您没有 insert into
标量变量。你可以做一个select into
。声明
select rid
into restname
from restaurant
where :new.rid = restaurant.rid;
在句法上是有效的。但这几乎可以肯定是不正确的。据推测,您想要 select 餐厅名称而不是 rid
select name
into restname
from restaurant
where :new.rid = restaurant.rid;
如果您声明了一个 %rowtype
变量,那么您想对该变量执行一个 select *
。否则,如果有人添加或删除列,您将来会遇到编译错误。您必须添加一个谓词来指定您想要 select 的行。我的猜测是你想要这样的东西来给出最低 best
分数的行(或者最低 rid
的行,如果有两个具有相同的低分数
select *
into minrow
from top5rest low
where not exists( select 1
from top5rest high
where low.best > high.best )
and not exists( select 1
from top5rest same
where low.best = same.best
and low.rid > same.rid )
但是,更根本的是,即使您纠正了语法错误,如果您尝试查询 rating
table,您也会遇到运行时变异 table 错误(您的视图所做的)来自 rating
table 上的行级触发器内部。那是不允许的。这几乎可以保证你的逻辑有问题。在这种情况下,似乎不需要单独的 table 来存储前 5 家餐厅。实际上,如果您需要实时结果,您的视图应该只进行该计算,或者如果您不需要在添加新评级时立即看到餐厅的整体评级变化,您应该创建一个定期刷新的物化视图。所以你可能根本不需要触发器。
所有被调用的table肯定存在。我也仔细检查了拼写。 sqldeveloper 给出的错误不是很有帮助,我似乎无法弄清楚为什么会失败。我正在尝试创建一个触发器,在收到新评论时更新 top5restaurants table。我有一个程序可以解析评论并将它们添加到评级 table。 top5restaurant table 保留了评分最高的 5 家餐厅。
drop view bestratings_rest;
create view bestratings_rest(rid, rate) as
(select distinct rid, max(stars) from rating
group by rid);
drop table top5restaurants;
create table top5restaurants(rid int);
insert into top5restaurants rid
select rid from
(select rid, rate from bestratings_rest r
order by r.rate asc)
where rownum <=5;
drop view top5rest;
create view top5rest as
select rid, best from(
select t.rid, best from top5restaurants t
inner join (select distinct rid, max(stars) as best from rating
group by rid) b
on t.rid = b.rid);
create or replace trigger top5_trigger
after insert on rating
for each row
declare
minrow top5rest%rowtype;
restrid restaurant.rid%type;
restname restaurant.name%type;
begin
insert into minrow
select rid, min(best) from top5rest;
insert into restname
select rid from restaurant
where :new.rid = restaurant.rid;
if :new.stars > minrow.best then
DELETE FROM top5restaurants
where top5restaurants.rid = :new.rid;
insert into top5restaurants values(rid);
end if;
end;
/
--
--
begin
update_reviews('Jade Court','Sarah M.', 4, '08/17/2017');
update_reviews('Shanghai Terrace','Cameron J.', 5, '08/17/2017');
update_reviews('Rangoli','Vivek T.',5,'09/17/2017');
update_reviews('Shanghai Inn','Audrey M.',2,'07/08/2017');
update_reviews('Cumin','Cameron J.', 2, '09/17/2017');
end;
/
select * from top5restaurants;
sqldeveloper 输出:
视图 BESTRATINGS_REST 已删除。
视图 BESTRATINGS_REST 已创建。
Table 排名前 5 的餐厅下降。
Table 创建了 TOP5 餐厅。
已插入 5 行。
查看 TOP5REST 已删除。
查看已创建的 TOP5REST。
触发TOP5_TRIGGER编译
LINE/COL错误
7/5 PL/SQL: SQL 语句被忽略 7/17 PL/SQL: ORA-00942: table 或视图不存在 11/5 PL/SQL:SQL 语句被忽略 11/17 PL/SQL: ORA-00942: table 或视图不存在 18/5 PL/SQL:SQL 语句被忽略 18/40 PL/SQL: ORA-00984: 此处不允许列 错误:检查编译器日志
您没有 insert into
标量变量。你可以做一个select into
。声明
select rid
into restname
from restaurant
where :new.rid = restaurant.rid;
在句法上是有效的。但这几乎可以肯定是不正确的。据推测,您想要 select 餐厅名称而不是 rid
select name
into restname
from restaurant
where :new.rid = restaurant.rid;
如果您声明了一个 %rowtype
变量,那么您想对该变量执行一个 select *
。否则,如果有人添加或删除列,您将来会遇到编译错误。您必须添加一个谓词来指定您想要 select 的行。我的猜测是你想要这样的东西来给出最低 best
分数的行(或者最低 rid
的行,如果有两个具有相同的低分数
select *
into minrow
from top5rest low
where not exists( select 1
from top5rest high
where low.best > high.best )
and not exists( select 1
from top5rest same
where low.best = same.best
and low.rid > same.rid )
但是,更根本的是,即使您纠正了语法错误,如果您尝试查询 rating
table,您也会遇到运行时变异 table 错误(您的视图所做的)来自 rating
table 上的行级触发器内部。那是不允许的。这几乎可以保证你的逻辑有问题。在这种情况下,似乎不需要单独的 table 来存储前 5 家餐厅。实际上,如果您需要实时结果,您的视图应该只进行该计算,或者如果您不需要在添加新评级时立即看到餐厅的整体评级变化,您应该创建一个定期刷新的物化视图。所以你可能根本不需要触发器。