Trigger is not called on update table in oracle - sql

I'm trying to make a trigger that updates the ID_ABONAMENT from the CONTRACTE table, when the ABONATI table is updated.
The problem is that the trigger is not called when I update a row in the ABONATI table.
Below is the trigger I made. Thank you in advance.
CREATE OR REPLACE TRIGGER UPDATE_CONTRACT_TRIGGER
AFTER UPDATE ON ABONATI
FOR EACH ROW
DECLARE
id_abonat number;
cod_abonament number;
BEGIN
id_abonat := :new.ID_ABONAT;
cod_abonament := :new.COD_ABONAMENT;
UPDATE CONTRACTE SET COD_ABONAMENT = cod_abonament WHERE ID_ABONAT = id_abonat;
END;
Thank you in advance.

You actually have a completely different problem - the trigger is being called but it's updating every row, each time it's updating a column to itself.
set COD_ABONAMENT = cod_abonament
WHERE ID_ABONAT = id_abonat;
These are going to be evaluated as referring to the columns in your table rather than the variables. So this is going to evaluate to true for every row which has an id_abonat value that isn't null and set the column to itself. You need to either use a different variable name or fully specify it in your update statement.
I would just forget about using a user defined variable here and just use :new.id_abonat in your update statement as is:
CREATE OR REPLACE TRIGGER UPDATE_CONTRACT_TRIGGER
AFTER UPDATE ON ABONATI
FOR EACH ROW
BEGIN
UPDATE CONTRACTE SET COD_ABONAMENT = :new.COD_ABONAMENT WHERE ID_ABONAT = :new.ID_ABONAT;
END;
/

Related

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;
/

Getting "invalid NEW or OLD specification" message when I try to run this

The entire question I'm trying to answer is:
Utilize the travel anywhere database to create a database trigger "hotel_kids_rule" to enforce a business rule. when inserting a hotel_reservation, if the num_kids value is more than zero, then assign the bed_type DQ to the reservation. save the trigger source as a script file.
For example, the trigger will change the bed_type for the following insert statement.
insert into hotel_reservation (reserve_no,reserve_date,arrival_date,dep_date,num_adults,num_kids,customer_id,hotel_id,bed_type,rooms)
values(hotel_reserve_sequence.nextval,sysdate,sysdate+5,sysdate+7,1,2,101,19,'DT',1);
For example, the trigger will not change the bed_type for the following insert statement.
insert into hotel_reservation (reserve_no,reserve_date,arrival_date,dep_date,num_adults,num_kids,customer_id,hotel_id,bed_type,rooms)
values(hotel_reserve_sequence.nextval,sysdate,sysdate+5,sysdate+7,2,0,102,20,'DT',1);
This is what I have so far:
create or replace trigger hotel_kids_rule
after insert or update on hotel_reservation
for each row
when (num_kids > 0)
declare
new_bed_type varchar2(20);
new_bed_type='DQ'
begin
new.bed_type=new_bed_type;
end;
Any help would be appreciated! Thanks!
I think you want a before trigger, so you can set the new value before it is written. Also, the way you access new is not ok: within the trigger code, you need :new.bed_type; in the when condition, you want new.num_kids.
This should work:
create or replace trigger hotel_kids_rule
before insert or update on hotel_reservation
for each row
when (new.num_kids > 0)
begin
:new.bed_type := 'DQ';
end;
/
Here is a small demo.
The assignment of your variable needs to be inside the actual code block. And the assignment operator is := in PL/SQL, not =. If you want the trigger to change anything you also need to create it as a BEFORE trigger:
create or replace trigger hotel_kids_rule
before insert or update on hotel_reservation
for each row
when (new.num_kids > 0)
declare
new_bed_type varchar2(20);
begin
new_bed_type := 'DQ';
:new.bed_type := new_bed_type;
end;
Note that the new record in the when condition is used without the colon : while inside the code block it needs to be referenced with the colon.
Alternatively initialize the variable when declaring it:
declare
new_bed_type varchar2(20) := 'DQ';
begin
:new.bed_type := new_bed_type;
end;
Or even simpler without any intermediate variable.
begin
:new.bed_type := 'DQ';
end;

PL/SQL ORACLE: Trigger updates on delete

I am trying to make a trigger that increases the booked value and decreases the available value whenever new record is inserted inside the table ticket_price. If a record is deleted, I want it to decrease the booked value and increase the available value.
Although I am able to successfully make the trigger work for INSERT, I am unable to do the same for updating the values on deletion of a record.T his is the error I get whenever I try to delete a record
ORA-01403: no data found
ORA-06512: at "K.CAL", line 6
ORA-04088: error during execution of trigger 'K.CAL'
Just to clarify, I am updating values in another table, not the same table I am deleting!
Here is my code for the trigger:
CREATE OR REPLACE TRIGGER cal
BEFORE INSERT OR DELETE ON TICKET_PRICE FOR EACH ROW
DECLARE
V_TICKET TICKET_PRICE.TICKETPRICE%TYPE;
V_BOOKED FLIGHTSEAT.BOOKED_SEATS%TYPE;
V_AVAILABLE FLIGHTSEAT.AVAILABLE_SEATS%TYPE;
BEGIN
SELECT BOOKED_SEATS,AVAILABLE_SEATS
INTO V_BOOKED,V_AVAILABLE
FROM FLIGHTSEAT
WHERE SEAT_ID=:NEW.SEAT_ID;
IF INSERTING THEN
V_BOOKED:=V_BOOKED+1;
V_AVAILABLE:=V_AVAILABLE-1;
UPDATE FLIGHTSEAT
SET BOOKED_SEATS=V_BOOKED, AVAILABLE_SEATS=V_AVAILABLE
WHERE SEAT_ID=:NEW.SEAT_ID;
ELSIF DELETING THEN
V_BOOKED:=V_BOOKED-1;
V_AVAILABLE:=V_AVAILABLE+1;
UPDATE FLIGHTSEAT
SET BOOKED_SEATS=V_BOOKED, AVAILABLE_SEATS=V_AVAILABLE
WHERE SEAT_ID=1;
END IF;
END;
You have correctly surmised that :new.seat is not available on the update for a delete. But neither is it available for the select and ow could you know sea_id=1 was need to be updated? For reference to Deleted row data use :Old.column name; is this case use :old_seat_id for both select and update.
But you don't need the select at all. Note: Further you have an implied assumption that seat_id is unique. I'll accept that below.
create or replace trigger cal
before insert or delete on ticket_price
for each row
declare
v_seat_id flightseat.seat_id%type;
v_booked flightseat.booked_seats%type;
begin
if INSERTING then
v_booked := 1;
v_seat_id := :new.seat_id;
else
v_booked := -1;
v_seat_id := :old.seat_id;
end if;
update flightseat
set booked_seats=booked_seats+v_booked
, available_seats=available_seats-v_booked
where seat_id = v_seat_id;
end;

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;/

PL/SQL table level trigger running after second update

I have this problem whith this trigger which is calling a procedure updating a table after updating a row in other table.The problem is that you have to update table STAVKARACUNA two times to table RACUN update but it uses old values. Here is a code of both:
Here is a code of aa procedure:
create or replace PROCEDURE ukupnaCenaRacun (SIF IN VARCHAR2) AS
SUMA float := 0;
suma2 float := 0;
Mesec NUMBER;
popust float :=0.1;
BEGIN
SELECT SUM(iznos) INTO SUMA
FROM STAVKARACUNA
WHERE SIF = SIFRARAC;
SELECT SUM(vredrobe*pdv) INTO SUMA2
FROM STAVKARACUNA
WHERE SIF = SIFRARAC;
SELECT EXTRACT (MONTH FROM DATUM) INTO Mesec FROM RACUN WHERE SIF=SIFRARAC;
IF(Mesec = 1) THEN
UPDATE RACUN
SET PDVIZNOS = SUMA2, ukupnozanaplatu = suma*(1-popust)
WHERE SIFRARAC=SIF;
END IF;
IF (MESEC != 1) THEN
UPDATE RACUN
SET PDVIZNOS = SUMA2, ukupnozanaplatu = suma
WHERE SIFRARAC=SIF;
END IF;
END;
Here is a trigger:
create or replace TRIGGER "UKUPNACENA_RACUN_UKUPNO"
AFTER INSERT OR UPDATE OR DELETE OF CENA,KOL,PDV ON STAVKARACUNA
DECLARE
SIF VARCHAR2(20) := PACKAGE_STAVKARACUNA.SIFRARAC;
BEGIN
PACKAGE_STAVKARACUNA.ISKLJUCI_TRIGER('FORBID_UPDATING');
ukupnaCenaRacun(SIF);
PACKAGE_STAVKARACUNA.UKLJUCI_TRIGER('FORBID_UPDATING');
END;
The problem is when a table STAVKARACUNA is updated, nothing happens with table RACUN, but next time table STAVKARACUNA is updated the data in table RACUN is updated but with old values.
Thank you very much.
Are you aware that a trigger for an event on a table should not directly access that table? The code is inside a DML event. The table is right in the middle of being altered in some say. So any query back to the same table could well attempt to read data that is in the process of being changed. It could try to read data that does not quite exist before a commit is performed or is one value now but will be a different value once a commit is performed. The table is mutating.
This goes for any code outside the trigger that the triggers calls. So the ukupnaCenaRacun procedure is executed in the context of the trigger. Yet it goes out and queries table STAVKARACUNA in two places (which can be placed in a single query but that is neither here nor there).
Since you're not getting a mutating table error, I can only assume that the update is not taking place until after the triggering event is committed but then you won't see the results until after that is committed sometime later -- like when the second update is committed.
That explanation actually sounds hollow to me as I have always thought that all activity performed by a trigger is committed or rolled back as part of one transaction. But that is the action you are describing.
It appears that SIF is a package variable defined in the package spec. Since everything in the procedure keys off that value and the trigger doesn't change the value, can't SUMA and SUMA2 also be defined as variables, values to be updated whenever SIF changes?