Creating a SQL trigger - oracle

I am trying to create a trigger on my database, using SQL, such that after an insert into the table HISTORY table, if, the attribute FINISHED="T", the MESSAGE attribute is "FINISHED" else, if FINISHED="F", the MESSAGE is "NOT FINISHED".
This is my code currently when I try to run this, it says
"Trigger created with compilation errors"
Could someone please tell me what is wrong with this statement? Thank you!
CREATE OR REPLACE TRIGGER MESSAGE_TR
AFTER INSERT
ON HISTORY
FOR EACH ROW
BEGIN
IF (HISTORY.FINISHED="T")
THEN
INSERT INTO HISTORY(MESSAGE) VALUES("FINISHED");
ELSEIF (HISTORY.FINISHED="F")
INSERT INTO HISTORY(MESSAGE)VALUES("NOT FINISHED");
END;
/

I think this is what you intend:
CREATE OR REPLACE TRIGGER MESSAGE_TR
BEFORE INSERT
ON HISTORY
FOR EACH ROW
BEGIN
:NEW.MESSAGE := (CASE WHEN :NEW.FINISHED = 'T' THEN 'FINISHED' ELSE 'NOT FINISHED' END);
END;
Note that this is a before insert trigger, because it intends to modify the row being inserted.

Related

Error: can't create trigger properly (ORA-24344: success with compilation error ORA-06512). Oracle SQL

Oracle APEX. I want to create trigger: if user deletes a row where ENDDATE is null the row won't be deleted overwise it will. This is my script:
CREATE OR REPLACE TRIGGER CHECK_NOT_NULL_
BEFORE DELETE ON CAREER
FOR EACH ROW
BEGIN
IF(OLD.ENDDATE IS NULL)
INSERT INTO CAREER VALUES (OLD.JOBNO, OLD.EMPNO, OLD.STARTDATE, OLD.ENDDATE);
END IF;
END CHECK_NOT_NULL_;
But I have ORA-24344 error. Can you explain why and what should I do to fix it?
Your trigger attempts to re-insert the row if the END_DATE is null. This won't work (you'll get the notorious mutating table error). But anyway, if you want to prevent deletion of the row it's simpler and clearer to simply do that:
CREATE OR REPLACE TRIGGER CHECK_NOT_NULL_
BEFORE DELETE ON CAREER
FOR EACH ROW
BEGIN
IF :OLD.ENDDATE IS NULL THEN
raise_application_error(-20000, 'Cannot delete a row when ENDDATE is null');
END IF;
END CHECK_NOT_NULL_;
This fails the action and tells the user why their action was refused. Silently undoing a user's action is bad practice, because it's mystifying, and mystified users are unhappy and often angry users.
Precede all olds with a colon :, i.e.
CREATE OR REPLACE TRIGGER CHECK_NOT_NULL_
BEFORE DELETE ON CAREER
FOR EACH ROW
BEGIN
IF(:OLD.ENDDATE IS NULL)
INSERT INTO CAREER VALUES (:OLD.JOBNO, :OLD.EMPNO, :OLD.STARTDATE, :OLD.ENDDATE);
END IF;
END CHECK_NOT_NULL_;
Also, I'd suggest you to name all columns you're inserting into, e.g.
insert into career (jobno, empno, startdate, enddate)
values (:old.jobno, :old.empno, :old.startdate, :old.enddate);

ORACLE - After trigger is not passing the value to the procedure

I have a problem with a "after insert" trigger which won't pass the value to a stored procedure that i'm calling inside the trigger.
It works ok for update and also i should mention that i am querying the table in the procedure that i am calling.
It goes something like:
create or replace trigger test_trg
after insert or update on table1
for each row
begin
test_procedure(:new.value1);
end;
The procedure looks inside table1 and inserts in table2 hints about what should be added in table1 based on the current inserted/updated row.
Thanks in advance!!
I found it!
The problem was not the trigger, it was in the procedure. I was performing a "dirty read" based on the record ID that i was sending (the record id of a new row).
Even though my trigger is "after insert" it looks like my row can't be found by the procedure and i was basing all my operations on it.
Fixed it by adding more parameters to the procedure and passing :new values straight from the trigger for everything i needed.
A trigger transaction is depend on its statement transaction. Therefore you can not read uncommitted records. So you should transfer "test_procedure" codes into your trigger and use :New record values to insert data into table2.
Your code should look like this:
create or replace trigger test_trg
after insert or update on table1
for each row
begin
if inserting then
insert into table2(ID, F1, F2, ...)
values (NEW_ID_VALUE, :NEW.F1_VALUE, :NEW.F2_VALUE, ...);
elsif updating then
update table2
set F1 = :NEW.F1_VALUE
, F2 = :NEW.F2_VALUE
where TABLE1_ID_FK = :NEW.ID;
end if;
end;

How to Update Column of one table if Another table column value becomes zero In Oracle?

I have two tables of ITEM(Menu_Id,Menu_Status) & STOCK(Stock_Id,Menu_Id,Stock_Quantity).
Now I want to update the Menu_Status column of ITEM table, when the Stock_Quantity column of STOCK table value will be zero.
And also I implement this on Oracle Apex 5.0 .
I want to handle this in backend of database, when customer orders and Stock_Quantity will be minus(-) according to number of quantity is ordered.
Which one better for this? Trigger or Procedure? Please help me by providing code.
I tried this code but having ORA-24344: success with compilation error message!
create or replace trigger "KITCHEN_T11"
AFTER
insert or update on "KITCHEN"
for each row
when (NEW.quantity<= 0)
begin
declare
mid number;
begin
select m_id into mid from kitchen where k_id=:new.k_id;
update menu_item set status=0 where m_id=mid;
end;
end;
You should anyhow write a procedure to update item table. Only choice need to make is to call it from where.
If you know all the process who are updating stock table, and if this procedure can be placed there, it will be best option.
In case it is not possible, you can call this procedure from trigger.
CREATE OR REPLACE TRIGGER "STOCK_T1"
AFTER
insert or update on "STOCK"
for each row
WHEN (NEW.stock_quantity<= 0)
begin
update item set menu_status=0 where menu_id=:NEW.MENU_ID;
end;

Getting the value that fired the Oracle trigger

Am very new to Oracle triggers. Suppose I have a trigger on an insert in the table emp. Is there a way to find out what was the inserted record that fired the trigger. I wanted the trigger to have code that does something if the inserted record was a particular value.
Assuming you have a row-level trigger, you can simply use the :NEW pseudo-record
CREATE TRIGGER name_of_trigger
BEFORE INSERT ON emp
FOR EACH ROW
DECLARE
<<declare variables>>
BEGIN
IF( :new.ename = 'JUSTIN' )
THEN
<<do something if the newly inserted ENAME value is 'JUSTIN'>>
END IF;
END;
For a DDL trigger, the approach is completely different. In that case, the pseudofunctions ora_dict_obj_owner and ora_dict_obj_name will return the owner and name of the table that the DDL statement is operating on.
The row that is being insertes is available as NEW in the trigger
Check out the manual for more details.
http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/create_trigger.htm#BABEBAAB
http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm#LNPLS99955

compile error when creating an "instead of" trigger for a view

I've created an "instead of" trigger for a simple view that only does select * on a table and a trigger that does nothing (I wanted to minimize the problem):
create or replace view tmp(id, nazwa, nip, adres, zalega, punkty) as
select * from klient
create or replace trigger tmp_trg
instead of insert
on tmp
for each row
begin
end;
The view is created.
Then when I want do declare this trigger sql developer returns error:
Error(8,1): PLS-00103: Encountered the symbol "END" when expecting one of the following: begin case declare exit for goto if loop mod null pragma raise return select update while with 'an identifier' 'a double-quoted delimited-identifier' 'a bind variable' << close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe
just add "null;" between the begin and the end.
a trigger that does nothing (I wanted to minimize the problem):
I'm not sure I understand why you need a trigger if it does nothing ?
To answer, there isn't a valid PL/SQL statement in your trigger code block, add a NULL to make it a valid block and have no action.
create or replace trigger tmp_trg
instead of insert
on tmp
for each row
begin
NULL;
end;

Resources