Why this trigger doesn't compile(oracle)? - sql

Error: SQL Statement ignored (underline UPDATE TABLE)
CREATE OR REPLACE TRIGGER CANCEL_TICKET
AFTER INSERT ON CANCEL
FOR EACH ROW
BEGIN
UPDATE TABLE TICKET
SET TICKET.TICKET_ID := NULL
WHERE TICKET.TICKET_ID = :NEW.TICKET_ID;
END;

there is no need for TABLE and a colon : is more in your statement, so better
UPDATE TICKET
SET TICKET.TICKET_ID = NULL

Related

how to convert a mutating trigger to a stored procedure

I have the following trigger:
CREATE OR REPLACE TRIGGER planning_trig BEFORE
UPDATE OF planned_remediation_date ON evergreen
FOR EACH ROW
DECLARE
planned_remediation_date DATE;
BEGIN
SELECT
planned_remediation_date
INTO planned_remediation_date
FROM
evergreen
WHERE
hostname = :new.hostname
AND instance_name = :new.instance_name
AND product_home = :new.product_home
AND it_service = :new.it_service
AND sw_name = :new.sw_name;
IF
planned_remediation_date IS NOT NULL
AND planned_remediation_date > trunc(sysdate)
THEN
UPDATE evergreen
SET
planning_status = 'planned';
ELSE
UPDATE evergreen
SET
planning_status = 'overdue';
END IF;
END;
/
After an update of the row in my table evergreen I get this error:
ORA-04091: table PTR.EVERGREEN is mutating, trigger/function may not see it
I believe the error comes from the fact that I'm trying to update the very same table the trigger is firing on. I read that the best way to handle updates in the same table are stored procedures but I'm quite new to oracle and don't know how to achieve that. Another possibility I heard is AUTONOMOUS_TRANSACTION Pragma but not sure either if this applies to my case.
A little more background, the underlying table has a composite unique key (hostname,instance_name,product_home,it_service,sw_name) and I want to update an existing column on this table called planning_status based on the updated value of planned_remediation_date. If that value is not null and greater then today then update with planned else overdue.
Expression planned_remediation_date IS NOT NULL is redundant. planned_remediation_date > trunc(sysdate) is never TRUE when planned_remediation_date is NULL.
Your trigger can be written much shorter:
CREATE OR REPLACE TRIGGER planning_trig
BEFORE UPDATE OF planned_remediation_date ON evergreen
FOR EACH ROW
BEGIN
IF :new.planned_remediation_date > trunc(sysdate) THEN
:new.planning_status := 'planned';
ELSE
:new.planning_status := 'overdue';
END IF;
END;
/
I guess you like to modify the updated row, not other rows in that table. Otherwise you would need a procedure or a COMPOUND trigger

How to change from oracle trigger to oracle compound trigger?

I have to change from given Oracle trigger:
CREATE OR REPLACE TRIGGER MY_TRIGGER
AFTER UPDATE OF STATUS ON T_TABLE_A
FOR EACH ROW
BEGIN
UPDATE T_TABLE_B T
SET T.STATUS = :NEW.STATUS
WHERE T.REF_ID = :NEW.ID;
END;
/
to an Oracle compound trigger. Effect must be the same. My approach is now:
CREATE OR REPLACE TRIGGER MY_NEW_TRIGGER
for insert or update on T_TABLE_A
compound trigger
before statement -- STUB
is
begin
null;
end before statement;
before each row
is
begin
end before each row;
after each row -- STUB
is
begin
--IDEA: collect ids of changed records (T_TABLE_A) here >> in a global variable? array?
end after each row;
after statement -- STUB
is
begin
--IDEA: Bulk Update of T_TABLE_B (goal is: update T_TABLE_B.STATUS column; must be the same as T_TABLE_A.STATUS)
end after statement;
end;
/
But as a Java Developer I am very slow to find out the correct syntax of variables, arrays and simple DB scriptings, so any approach is helpful.
Approach where to start is marked as "IDEA".
As I can see you have almost done the half of the job , I amended the code to IDEA part.
I have not included the before statement part and also the triggering clause and all you can adjust according to your need. I just considered for updating the status column in my code.
CREATE OR REPLACE TRIGGER my_trigger
FOR UPDATE OF status ON t_table_a
COMPOUND TRIGGER
-- record type to hold each record updated in t_table_a
-- columns we are intersted in are id and status
TYPE table_a_rec IS RECORD(
id t_table_a.id%TYPE
,status t_table_a.status%TYPE);
--table type based on record to access each record using this
TYPE table_a_row_data_t IS TABLE OF table_a_rec INDEX BY PLS_INTEGER;
-- global variable for the compound trigger
g_row_level_data table_a_row_data_t;
AFTER EACH ROW IS
BEGIN
-- IDEA: collect ids of changed records (T_TABLE_A) here >> in a global variable? array?
g_row_level_data(g_row_level_data.count + 1).id := :new.id;
g_row_level_data(g_row_level_data.count).status := :new.status;
END AFTER EACH ROW;
AFTER STATEMENT IS
BEGIN
--IDEA: Bulk Update of T_TABLE_B (goal is: update T_TABLE_B.STATUS column; must be the same as T_TABLE_A.STATUS)
FORALL i IN 1 .. g_row_level_data.count
UPDATE t_table_b t
SET t.status = g_row_level_data(i).status
WHERE t.ref_id = g_row_level_data(i).id;
END AFTER STATEMENT;
END my_trigger;
/

Update column in another table with trigger

I would like to update a column in another table with the code below but I get a error that the trigger is invalid.
Whats wrong with it?
CREATE OR REPLACE TRIGGER UPDATE_PAYMENT
AFTER INSERT OR UPDATE ON PAYMENT
for each row
begin
update PAYMENTTYPE PT
set PT.PAYMENTTYPECOLUMN = PAYMENT.PAYMENTTYPECOLUMN
where PT.ID = :NEW.ID and PT.ID2 = :NEW.ID2;
end UPDATE_PAYMENT;
In your trigger you refer twice to PAYMENT columns by :NEW., and this is correct, while the third time you use PAYMENT., which is wrong.
The trigger should be:
CREATE OR REPLACE TRIGGER UPDATE_PAYMENT
AFTER INSERT OR UPDATE ON PAYMENT
for each row
begin
update PAYMENTTYPE PT
set PT.PAYMENTTYPECOLUMN = :NEW.PAYMENTTYPECOLUMN -- <------ HERE
where PT.ID = :NEW.ID and PT.ID2 = :NEW.ID2;
end UPDATE_PAYMENT;

Create Before Insert Trigger in oracle and implement in asp.net web form

I have a requirement of which I want to create a trigger in Oracle.
So what I want is: I have a table called XXCUS.XXACL_PN_PROSPECT_TRL in which there is a column called ACTION whose default value is set as RELEASE, EXTEND and CANCEL.
So my trigger would be on the table XXCUS.XXACL_PN_PROSPECT_TRL as
whenever the column ACTION has values as
RELEASE then the other table column should get UPDATED as R with the same matching ID
EXTEND then the other table column should get UPDATED as O with the same matching ID
CANCEL then the other table column should get UPDATED as C with the same matching ID
The other table name is xxcus.xxacl_pn_leases_all whose column needs to be updated. Also the column name is CLOSE_FLAG.
I m trying like below
CREATE [ OR REPLACE ] TRIGGER XXACL_PN_PROSPECT_T
BEFORE INSERT
ON XXCUS.XXACL_PN_PROSPECT_TRL
[FOR EACH ROW]
DECLARE
-- variable declaration
BEGIN
-- trigger code
Insert into XXCUS.XXACL_PN_PROSPECT_TRL -- values for ACTION here
then
update xxcus.xxacl_pn_leases_all if 'RELEASE' then 'R', if 'EXTEND' then 'O' where mkey = dynamic
EXCEPTION
WHEN ...
-- exception handling
END;
but it is not working as I am not champ in creating Triggers. Kindly help me with this
There are some obvious syntax errors
You don't need square brackets. Those are in the documentation to indicate optional parts.
Your insert/update statements are wrong, need to correct them.
It should look on the lines of :
CREATE OR REPLACE TRIGGER XXACL_PN_PROSPECT_T
BEFORE INSERT
ON XXCUS.XXACL_PN_PROSPECT_TRL
DECLARE
-- variable declaration
BEGIN
UPDATE xxcus.xxacl_pn_leases_all
SET CLOSE_FLAG = DECODE(:NEW.ACTION, 'RELEASE','R','EXTEND','O', 'CANCEL','C')
WHERE ID = :NEW.ID
END;
This trigger will update CLOSE_FLAG column of xxcus.xxacl_pn_leases_all based on what value comes in Action column of XXACL_PN_PROSPECT_TRL table.
While going through the links and documentation, I tried my self and figured out the solution.
There were many syntax errors in the starting. But I guess, I was the only one to apply the exact logic and took help of the syntax online.
So here it was my TRIGGER which I wrote and it worked perfectly.
CREATE OR REPLACE TRIGGER xxcus.xxacl_pn_prospect_trl_trg
AFTER INSERT OR UPDATE
ON xxcus.xxacl_pn_prospect_trl
FOR EACH ROW
DECLARE
sql_error VARCHAR (10000);
v_mkey NUMBER;
v_action VARCHAR (10);
BEGIN
v_action := :NEW.action;
IF (v_action = 'Extend')
THEN
UPDATE xxcus.xxacl_pn_leases_all
SET no_of_days = :NEW.current_action_days
WHERE lease_num = :NEW.lease_no;
ELSIF (v_action = 'Release')
THEN
UPDATE xxcus.xxacl_pn_leases_all
SET no_of_days = 0,
close_flag = 'R'
WHERE lease_num = :NEW.lease_no;
ELSE
UPDATE xxcus.xxacl_pn_leases_all
SET no_of_days = 0,
close_flag = 'C'
WHERE lease_num = :NEW.lease_no;
END IF;
EXCEPTION
WHEN OTHERS
THEN
sql_error := SQLERRM; END;/

UPDATE table with PL/SQL trigger?

I have this trigger, and I am getting an arror message when I run it; "bad bind variable".
I can't seem to see where the problem lies. Any help would be appreciated.
create or replace TRIGGER trg_placed AFTER UPDATE
OF STATUS_ID ON STATUS
FOR EACH ROW
BEGIN
IF :new.STATUS_ID = 7
THEN
UPDATE STUDENT
SET PLACED_Y_N = 'Y'
WHERE RECORD_NUMBER = :NEW.record_number;
END IF;
END;
try like this:
create or replace TRIGGER trg_placed AFTER UPDATE
OF STATUS_ID ON STATUS
REFERENCING OLD AS o NEW AS n
FOR EACH ROW
BEGIN
IF n.STATUS_ID = 7
THEN
UPDATE STUDENT
SET PLACED_Y_N = 'Y'
WHERE RECORD_NUMBER = n.record_number;
END IF;
END;
If you use lowercase for Oracle objects, you'll have to surround object names with quotes (") and match the case exactly to get it to work.
like this
create or replace TRIGGER trg_placed AFTER UPDATE
OF STATUS_ID ON STATUS
FOR EACH ROW
BEGIN
IF :new.STATUS_ID = 7
THEN
UPDATE STUDENT
SET PLACED_Y_N = 'Y'
WHERE RECORD_NUMBER = :NEW."record_number"; --quotes (") required for column name.
END IF;
END;