问题
I am trying to write a trigger to populate a table containing information on an employee's updated salary. I'm having a problem that I can't quite wrap my head around at the moment.
Here is the table to be populated:
drop table SalUpdates cascade constraints;
create table SalUpdates(
SalSSN char(9),
newSalary decimal(10,2),
oldSalary decimal(10,2)
);
This is my trigger:
create or replace trigger t1
after update of salary on employee
for each row
begin
insert into SalUpdates values (:old.Ssn, :new.salary, :old.salary);
end;
The trigger compiles with no issues, but when I try to run this update, Oracle tells me my trigger is invalid. What could be causing this?
update employee
set salary=4000
where ssn='123456789';
回答1:
You've shown the code in chunks. but it seems you're running what you've shown together as a script, initially without the update:
drop table SalUpdates cascade constraints;
create table SalUpdates(
SalSSN char(9),
newSalary decimal(10,2),
oldSalary decimal(10,2)
);
create or replace trigger t1
after update of salary on employee
for each row
begin
insert into SalUpdates values (:old.Ssn, :new.salary, :old.salary);
end;
When run as a script in SQL Developer the script output window shows:
drop table SalUpdates cascade constraints
Error report -
ORA-00942: table or view does not exist
00942. 00000 - "table or view does not exist"
*Cause:
*Action:
Table SALUPDATES created.
Trigger T1 compiled
If you then add the update statement to the script:
drop table SalUpdates cascade constraints;
create table SalUpdates(
SalSSN char(9),
newSalary decimal(10,2),
oldSalary decimal(10,2)
);
create or replace trigger t1
after update of salary on employee
for each row
begin
insert into SalUpdates values (:old.Ssn, :new.salary, :old.salary);
end;
update employee
set salary=4000
where ssn='123456789';
you get:
Table SALUPDATES dropped.
Table SALUPDATES created.
Trigger T1 compiled
Errors: check compiler log
If you then try to run the update on it's own (as a statement instead of a script; or by selecting that test and running as a script) you do indeed get:
SQL Error: ORA-04098: trigger 'MYSCHEMA.T1' is invalid and failed re-validation
04098. 00000 - "trigger '%s.%s' is invalid and failed re-validation"
*Cause: A trigger was attempted to be retrieved for execution and was
found to be invalid. This also means that compilation/authorization
failed for the trigger.
*Action: Options are to resolve the compilation/authorization errors,
disable the trigger, or drop the trigger.
If you query the user_errors
view, or run show errors
, you'll see:
PLS-00103: Encountered the symbol "UPDATE"
The problem is that you aren't completing the create trigger
statement properly. The update
is being seen as part of the same PL/SQL block; an invalid part, but still included.
When you have a PL/SQL block you have to terminate it with a slash, as it explains in the SQL*Plus documentation (which mostly applies to SQL Developer too):
SQL*Plus treats PL/SQL subprograms in the same manner as SQL commands, except that a semicolon (;) or a blank line does not terminate and execute a block. Terminate PL/SQL subprograms by entering a period (.) by itself on a new line. You can also terminate and execute a PL/SQL subprogram by entering a slash (/) by itself on a new line.
SQL Developer doesn't complain if the last block in a script doesn't have a terminating slash though, so your original script (without the update) works; in SQL*Plus it would sit at a prompt. It kind of infers that it should be there - trying to be helpful. When you add the update
statement it is no longer the end of the script so that doesn't apply.
If you add a slash to your script between the PL/SQL code and the following SQL statement it all works:
drop table SalUpdates cascade constraints;
create table SalUpdates(
SalSSN char(9),
newSalary decimal(10,2),
oldSalary decimal(10,2)
);
create or replace trigger t1
after update of salary on employee
for each row
begin
insert into SalUpdates values (:old.Ssn, :new.salary, :old.salary);
end;
/
update employee
set salary=4000
where ssn='123456789';
and you now see:
Table SALUPDATES dropped.
Table SALUPDATES created.
Trigger T1 compiled
1 row updated.
来源:https://stackoverflow.com/questions/43479838/pl-sql-trigger-issues