Error creating trigger in Oracle PLSQL - sql

I'm a student learning SQL in Oracle. I'm creating a trigger and within the trigger I'm calling a procedure update_price_history(item_id, NEW.price).
This is the statement I did,
CREATE OR REPLACE TRIGGER upd_hist_trg
BEFORE INSERT OR UPDATE OF price ON Item
FOR EACH ROW
BEGIN
IF :NEW.price != price THEN
update_price_history(item_id, NEW.price)
END IF;
END;
I thought I had everything correct but I'm getting an error message:
Error(3,2): PLS-00103: Encountered the symbol "END" when expecting one of the following: := . ( % ; The symbol ";" was substituted for "END" to continue.
I've been trying to figure out what I'm getting wrong and I'm not seeing what it is. Any help would be greatly appreciated.

You forgot the semicolon at the end
...
update_price_history(item_id, :NEW.price);
...

Try this :
CREATE OR REPLACE TRIGGER upd_hist_trg
BEFORE INSERT OR UPDATE OF price ON Item
FOR EACH ROW
DECLARE
item_id number;
BEGIN
IF :NEW.price != price THEN
update_price_history(item_id, :NEW.price);
END IF;
END;
you forgot : in front of new and a semicolon ; after procedure. By the way, i can't see any variable definition of item_id.

Related

how to fix this trigger error in PostgreSQL [duplicate]

This question already has answers here:
syntax Error in PostgreSQL when I try to create Trigger
(2 answers)
Closed last year.
I am getting a syntax error for my code which I can't understand why
am I missing something?
also, I read this I did not get my answer
syntax Error in PostgreSQL when I try to create Trigger
CREATE TRIGGER MyExampleName AFTER INSERT ON baskets
FOR EACH ROW BEGIN
UPDATE customers
SET customers.credit=customers.credit - NEW.amount
WHERE customers.id = NEW.customer_id;
END;
and tried it like this as well:
CREATE TRIGGER MyExampleName AFTER INSERT ON baskets
FOR EACH ROW AS $$ BEGIN
UPDATE customers
SET customers.credit=customers.credit - NEW.amount
WHERE customers.id = NEW.customer_id;
END;
$$ LANGUAGE plpgsql;
Error:
ERROR: syntax error at or near "BEGIN"
LINE 2: FOR EACH ROW BEGIN
^
SQL state: 42601
Character: 67
I'd say the first comment on your question pretty much covers it all. You cannot put the trigger code in the trigger body, you must first create a separate function and include the function call inside the trigger body.
This example comes directly from the Postgres docs:
-- 1. Create the function that does what you need
CREATE FUNCTION emp_stamp() RETURNS trigger AS $emp_stamp$
BEGIN
-- Check that empname and salary are given
IF NEW.empname IS NULL THEN
RAISE EXCEPTION 'empname cannot be null';
END IF;
IF NEW.salary IS NULL THEN
RAISE EXCEPTION '% cannot have null salary', NEW.empname;
END IF;
-- Who works for us when they must pay for it?
IF NEW.salary < 0 THEN
RAISE EXCEPTION '% cannot have a negative salary', NEW.empname;
END IF;
-- Remember who changed the payroll when
NEW.last_date := current_timestamp;
NEW.last_user := current_user;
RETURN NEW;
END;
$emp_stamp$ LANGUAGE plpgsql;
-- 2. Create the trigger with the 'EXECUTE FUNCTION function_name' part
-- replacing the actual function name from step 1.
CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp
FOR EACH ROW EXECUTE FUNCTION emp_stamp();

Unable to call a stored procedure from the trigger

CREATE OR REPLACE PROCEDURE UPDATE_AGE_VALUES
IS
cursor_ssn_number tbl_Patient.ssn_number%type;
cursor_patient_age tbl_Patient.patient_age%type;
age1 tbl_Patient.patient_age%type;
age2 tbl_Patient.patient_age%type;
age3 tbl_Patient.patient_age%type;
ssn_number1 tbl_Patient.ssn_number%type;
ssn_number2 tbl_Patient.ssn_number%type;
ssn_number3 tbl_Patient.ssn_number%type;
average number:=0;
i number:=1;
CURSOR cursor_tbl_Patient IS
SELECT ssn_number,patient_age FROM tbl_Patient ORDER BY patient_age ASC;
BEGIN
OPEN cursor_tbl_Patient;
LOOP
FETCH cursor_tbl_Patient into cursor_ssn_number,cursor_patient_age;
EXIT WHEN cursor_tbl_Patient%NOTFOUND;
IF i=1 THEN
age1:=cursor_patient_age;
ssn_number1:=cursor_ssn_number;
i:=i+1;
ELSIF i=2 THEN
age2:=cursor_patient_age;
ssn_number2:=cursor_ssn_number;
i:=i+1;
ELSIF i=3 THEN
age3:=cursor_patient_age;
ssn_number3:=cursor_ssn_number;
average:=(age1+age2+age3)/3;
UPDATE tbl_Patient SET patient_age=average where ssn_number IN (ssn_number1,ssn_number2,ssn_number3);
i:=1;
average:=0;
commit;
END IF;
END LOOP;
CLOSE cursor_tbl_Patient;
END;
/
CREATE OR REPLACE TRIGGER CHANGE_ROW_VALUES
AFTER INSERT ON tbl_Patient
FOR EACH ROW
BEGIN
CALL UPDATE_AGE_VALUES;
END;
/
Above code tries to modify the row values after a row is inserted. The procedure is created a execute.But I'm not able to call the procedure from the Trigger. I don't know why.
The error I'm getting is :
2/7 ,PLS-00103: Encountered the symbol "UPDATE_AGE_VALUES" when
,expecting one of the following:
,:= . ( # % ;
,The symbol ":=" was substituted for "UPDATE_AGE_VALUES" to
,continue.
Am I missing out anything?
Thanks in advance!!!
CALL is not a valid statement in PL/SQL. To call a procedure in PL/SQL you just need to give its name, as in:
CREATE OR REPLACE TRIGGER CHANGE_ROW_VALUES
AFTER INSERT ON tbl_Patient
FOR EACH ROW
BEGIN
UPDATE_AGE_VALUES;
END;
Your next problem will be that the UPDATE_AGE_VALUES reads and updates tbl_Patient, which will fail because UPDATE_AGE_VALUES is called from a row trigger which is defined on tbl_Patient. If you remove the FOR EACH ROW from the trigger it might work, but I won't answer for the performance.
Share and enjoy.
CREATE OR REPLACE TRIGGER CHANGE_ROW_VALUES
AFTER INSERT ON tbl_Patient
FOR EACH ROW
BEGIN
UPDATE_AGE_VALUES();
END;
This worked for me!!!

PLS-00103: Encountered the symbol "FETCH" when expecting one of the followingg

Created a procedure as below :
create or replace
PROCEDURE TEST AS
BEGIN
DECLARE
c_service process_state.service%type;
c_tr_source process_state.tr_source%type;
CURSOR c_process_state is
SELECT service, tr_source FROM process_state;
OPEN c_process_state;
LOOP
FETCH c_process_state into c_service, c_tr_source;
insert into process_state_archive values (c_service, c_tr_source);
commit;
EXIT WHEN c_process_state%notfound;
END LOOP;
CLOSE c_process_state;
END TEST;
After compiling i ran into some errors:
Error(33,4): PLS-00103: Encountered the symbol "FETCH" when expecting one of the following: constant exception table long double ref char time timestamp interval date
Error(44,4): PLS-00103: Encountered the symbol "CLOSE" when expecting one of the following: end not pragma final instantiable volgorde overriding static member constructor map
Can anyone one please explain the problem? I am beginner and learning SQL.
1) You should declare cursor before BEGIN but not after and EXIST WHEN should be immediately after FETCH
create or replace
PROCEDURE TEST AS
c_service process_state.service%type;
c_tr_source process_state.tr_source%type;
CURSOR c_process_state is
SELECT service, tr_source FROM process_state;
BEGIN
OPEN c_process_state;
LOOP
FETCH c_process_state into c_service, c_tr_source;
EXIT WHEN c_process_state%notfound;
insert into process_state_archive values (c_service, c_tr_source);
commit;
END LOOP;
CLOSE c_process_state;
END TEST;
2) You task seems can be solved in one statement instead of a lot of code with cursor:
INSERT INTO process_state_archive select service, tr_source FROM process_state;

PL SQL trigger using raise_application_error thows error.

I have a few things of code I need help debugging but I feel that if I can get one of them running i'll be able to get the rest(oh how i hope).
create or replace
trigger minimumwage
before insert or update on Employee
for each row
begin
if :new.Wage < 7.25
then raise_application_error('-20000,Pay is below Texas minimum wage!');
end if;
end;
/
I'm trying to do this on a table ran on my school's server through sqlplus if that helps.
When you're getting an error, it's always helpful to specify what error. There is a syntax error in the raise_application_error call in your trigger. That procedure takes two arguments, a number and a string. You are passing in a single argument that is one long string.
create or replace trigger minimumwage
before insert or update on Employee
for each row
begin
if :new.Wage < 7.25
then
raise_application_error(-20000,'Pay is below Texas minimum wage!');
end if;
end;
should be valid assuming there is a WAGE column in your EMPLOYEE table.
create or replace trigger deny_dec_pu before update of PU on ARTICLE
for each row
declare
erreur_pu exception;
begin
*insert into erreur values ('Operation de MAJ',sysdate);*
-- this intruction is never executec why ?
if (:new.pu < :old.pu) then
raise erreur_pu ;
end if;
exception
when erreur_pu then
Raise_application_error(-20100, 'rrrrrrrr', FALSE);
end;
/

Oracle SQL trigger results in compilation error

I have a problem with trigger not working. Here is my trigger code
create or replace trigger "ZIVOTINJE_T2"
BEFORE
insert or update on "ZIVOTINJE"
for each row
begin
IF new.cijena>10 THEN
:new.cijena:=9.9
ELSEIF new.cijena<0 THEN
:new.cijena:=0.1
END IF;
end;
When I try to insert entity in table ZIVOTINJE, I get this
ORA-04098: trigger 'DENISS.ZIVOTINJE_T2' is invalid and failed re-validation
I can see three problems in the code of your trigger:
You need to refer to the new values of the row using :new (including the colon), not new.
To change values that are about to be inserted/updated, write :new.cijena := 9.9; instead of SET new.cijena=9.9. Note that (a) there is no SET keyword here; (b) the assignment operator is :=, not =; and (c) you need a semi-colon at the end of the line.
Use ELSIF instead of ELSEIF.
Finally, in SQL*Plus, you can use SHOW ERRORS TRIGGER "ZIVOTINJE_T2" to show the errors for this trigger.
try this.
CREATE OR REPLACE TRIGGER "ZIVOTINJE_T2"
BEFORE
insert or update on "ZIVOTINJE"
for each row
begin
IF :new.cijena = 10 THEN
:new.cijena := 9.9;
ELSE
IF :new.cijena < 0 THEN
:new.cijena := 0.1;
END IF;
end if;
end;