为啥我的 PL/SQL 触发器会引发“错误(2,2):PL/SQL:语句被忽略”和“错误(2,5):PLS-00204:函数或伪列'EXISTS'”错误?
Posted
技术标签:
【中文标题】为啥我的 PL/SQL 触发器会引发“错误(2,2):PL/SQL:语句被忽略”和“错误(2,5):PLS-00204:函数或伪列\'EXISTS\'”错误?【英文标题】:Why is my PL/SQL trigger raising an "Error(2,2): PL/SQL: Statement ignored" and an "Error(2,5): PLS-00204: function or pseudo-column 'EXISTS' " error?为什么我的 PL/SQL 触发器会引发“错误(2,2):PL/SQL:语句被忽略”和“错误(2,5):PLS-00204:函数或伪列'EXISTS'”错误? 【发布时间】:2016-04-05 07:39:29 【问题描述】:我正在尝试编写一个触发器,如果学生已经在上他们试图成为助教的课程,该触发器会阻止插入到我的助教(助教)表中。据我了解,最好的方法(除了唯一约束,这必须是触发器)是通过使用回滚,我也在使用 raiserror。
create or replace trigger CheckTA
after insert
on TA for each row
begin
if exists (select * from Enrolls where Student_ID = :new.Student_ID and Course_ID = :new.Course_ID) then
rollback;
raiserror('TA enrolled in course as student');
end if;
end;
在创建触发器时,我遇到了以下错误:
错误(2,2):PL/SQL:语句被忽略
错误(2,5):PLS-00204:函数或伪列“EXISTS”只能在 SQL 语句中使用
触发器仍然会被创建,但是当不正确的值被插入到 TA 中时它不会触发。
表格:TA
Create table TA
(
Student_ID int references Student(Student_ID),
Course_ID int references Course(Course_ID),
Courses_taught varchar2(250),
Office_hours varchar2(25)
);
学生
create table Student
(
Student_ID int primary key,
Name varchar2(50),
Start_began int,
Semester_began varchar2(50),
GPA int,
Degree_status varchar2(25),
Degree_type varchar2(50),
Courses_Taken varchar2(250),
JI_list varchar2(250),
Profile_status varchar2(50)
);
课程
create table Course
(
Course_ID int primary key,
Course_Name varchar2(25)
);
注册
create table Enrolls
(
Student_ID int references Student(Student_ID),
Course_ID int references Course(Course_ID)
);
存储过程 这是我用来插入应该触发触发器的 TA 值的 SP。它不会引发错误,但我会把它放在这里以防万一。
create or replace procedure addTA (s_id int, c_id int, course varchar2)
as
begin
insert into TA (Student_ID,Course_ID,Courses_taught)
values (s_id,c_id,course);
end;
老实说,我不太确定这些错误是什么意思,更不用说是什么导致了它们,但我仍然尝试弄乱 raiserror 的语法,并用 raise_application_error 替换它,但没有运气。如果有人可以帮助我解决或至少解释这些错误,将不胜感激。当然,如果我的触发器有任何明显错误,请告诉我。
【问题讨论】:
使用触发器强制执行此类业务约束通常是一个坏主意,因为它们在多用户场景中往往会失败。想想如果第二个会话向enrolls
表添加一行,但仅在第一个会话向TA
表添加一行后才提交,会发生什么情况。一个适当的唯一约束是要走的路(你已经提到这是一种替代方法,顺便说一句)。
【参考方案1】:
错误提示“函数或伪列 'EXISTS' 只能在 SQL 语句中使用”,这意味着您只能在 SQL 语句中使用 EXISTS
,而在 PL/SQL 语句中使用 in .
如果你需要检查一些记录是否存在,你可以试试这样:
vNum number;
...
select count(1)
into vNumber
from Enrolls
where Student_ID = ...
if vNumber > 0 then
...
else
...
end if;
【讨论】:
以上是关于为啥我的 PL/SQL 触发器会引发“错误(2,2):PL/SQL:语句被忽略”和“错误(2,5):PLS-00204:函数或伪列'EXISTS'”错误?的主要内容,如果未能解决你的问题,请参考以下文章
为啥不允许在 PL/SQL 触发器中使用 ROLLBACK 语句,但 RAISE_APPLICATION_ERROR 是?
为啥 oracle 中的应用程序上下文使用 PL/SQL 过程