I want to write a trigger for a table "TRANSACTION".When a new line is inserted, I want to trigger to update the field "TRANSACTIONID" to the maximum + 1 of all the previous records.
I on't know much about SQL. Can someone help me?
many thanks
This is a really bad idea for a multi-user environment, as it will serialise inserts into the table. The usual approach is to use an Oracle sequence:
create sequence transaction_seq;
create trigger transaction_bir before insert on transaction
for each row
begin
:new.id := transaction_seq.nextval;
end;
To write a trigger based solution that actually got the max current value plus 1, you would need to write a complex 3-trigger solution to avoid the "mutating table" issue. Or you could create a simpler solution using another table to hold the current maximum value like this:
create table transaction_max (current_max_id number);
insert into transaction_max values (0);
create trigger transaction_bir before insert on transaction
for each row
declare
l_current_max_id number;
begin
update transaction_max set current_max_id = current_max_id + 1
returning current_max_id into l_current_max_id;
:new.id := l_current_max_id;
end;
This will avoid the mutating table issue and will serialize (slow down) inserts, so I don't see any advantage of this over using a sequence.
CREATE TRIGGER trigger1 on TransactionTable
INSTEAD OF INSERT
AS
BEGIN
DECLARE #MaxTranId INT
SELECT
#MaxTranId = MAX(TransactionId)
FROM
TransactionTable
INSERT INTO TransactionTable
SELECT
#MaxTranId + 1 ,
RestOfYourInsertedColumnsHere ,
FROM
inserted
END
GO
Related
create or replace NONEDITIONABLE TRIGGER SumUpdate AFTER INSERT ON stavkaotpremnice FOR EACH ROW
declare pragma autonomous_transaction;
begin
UPDATE otpremnica a
set a.ukupno=
(SELECT SUM(ukupno)
FROM stavkaotpremnice
WHERE brojotpremnice =: new.brojotpremnice)
WHERE a.brojotpremnice = :new.brojotpremnice;
commit;
end;
This trigger is to sum values of a column called "ukupno" in table stavakaotpremnice then store it in another table otpremnica in a column also called "ukupno".
The trigger check if the id(brojotpremnice) is the same and make the sum.
Brojotpremnice is a foreign key from table otpremnica.
Does anyone know why it is totally ignoring the first entry?
If i put rows in stavkaotpremnica i just count the first entry.
This type of problem can be solved via incremental addition as follows:
UPDATE otpremnica a
set a.ukupno = a.ukupno + :new.ukupno
WHERE a.brojotpremnice = :new.brojotpremnice;
Also, please read about pragma autonomous_transaction. Why it is used? Intentional? If you have no idea, read it. (It separates the transaction)
I want a trigger that updates the value of a column, but I just want to update a small set of rows that depends of the values of the inserted row.
My trigger is:
CREATE OR REPLACE TRIGGER example
AFTER INSERT ON table1
FOR EACH ROW
BEGIN
UPDATE table1 t
SET column2 = 3
WHERE t.column1 = :new.column1;
END;
/
But as I using FOR EACH ROW I have a problem when I try it, I get the mutating table runtime error.
Other option is not to set the FOR EACH ROW, but if I do this, I dont know the inserted "column1" for comparing (or I dont know how to known it).
What can I do for UPDATING a set of rows that depends of the last inserted row?
I am using Oracle 9.
You should avoid the DML statements on the same table as defined in a trigger. Use before DML to change values of the current table.
create or replace trigger example
before insert on table1
for each row
begin
:new.column2 := 3;
end;
/
You can modify the same table with pragma autonomous_transaction:
create or replace trigger example
after insert on table1 for each row
declare
procedure setValues(key number) is
pragma autonomous_transaction;
begin
update table1 t
set column2 = 3
where t.column1 = key
;
end setValues;
begin
setValues(:new.column1);
end;
/
But I suggest you follow #GordonLinoff answere to your question - it's a bad idea to modify the same table in the trigger body.
See also here
If you need to update multiple rows in table1 when you are updating one row, then you would seem to have a problem with the data model.
This need suggests that you need a separate table with one row per column1. You can then fetch the value in that table using join. The trigger will then be updating another table, so there will be no mutation problem.
`create table A
(
a INTEGER,
b CHAR(10)
);
create table B
(
b CHAR (10),
d INTEGER
);
create trigger trig1
AFTER INSERT ON A
REFERENCING NEW AS newROW
FOR EACH ROW
when(newROW.a<=10)
BEGIN
INSERT into B values(:newROW.b,:newROW.a);
END trig1;
insert into A values(11,'Gananjay');
insert into A values(5,'Hritik');
select * from A;
select * from B;`
I've created a trigger as follows:
create or replace trigger "PASSENGERS_BACKUP_T1"
after
insert or update or delete on "PASSENGERS"
for each row
begin
if :NEW."P_ID" is NOT null then
INSERT INTO PASSENGERS_BACKUP(
PB_ID,
PB_FIRST_NAME,
PB_LAST_NAME,
PB_STREET_ADDRESS1,
PB_STREET_ADDRESS2,
PB_CITY,
PB_STATE,
PB_POSTAL_CODE,
PB_EMAIL,
PB_PHONE_NUMBER1,
PB_PHONE_NUMBER2,
PB_URL,
PB_CREDIT_LIMIT,
PB_TAGS)
VALUES (
:new.P_ID,
:new.P_FIRST_NAME,
:new.P_LAST_NAME,
:new.P_STREET_ADDRESS1,
:new.P_STREET_ADDRESS2,
:new.P_CITY,
:new.P_STATE,
:new.P_POSTAL_CODE,
:new.P_EMAIL,
:new.PHONE_NUMBER1,
:new.PHONE_NUMBER1,
:new.URL,
:new.CREDIT_LIMIT,
:new.TAGS);
end if;
end;
now, when I update​ an existing row in "passengers" table as per the above trigger another new row is getting added in "passengers_backup" table instead I would like to update the existing row whenever an update is done in "passengers" table rows. As, well If I delete a row in "Passengers" table, if that row exists in 'Passengers_backup' table it should also get deleted. How can I acheive this?
Thanks in advance.
For solving your problem you need to use trigger with corresponding SQL statement for each action: insert, update, delete. As variant you can use something like this (Note, I left only two columns from your example for readability, so modify your trigger as you need):
create or replace trigger "PASSENGERS_BACKUP_TIUD"
after insert or update or delete on "PASSENGER"
for each row
begin
if inserting then
insert into "PASSENGER_BACKUP" (pb_id, pb_first_name)
values (:NEW.pb_id, :NEW.pb_first_name);
elsif updating then
update "PASSENGER_BACKUP"
set pb_id=:NEW.pb_id, pb_first_name=:NEW.pb_first_name
where pb_id=:NEW.pb_id;
elsif deleting then
delete from "PASSENGER_BACKUP"
where pb_id=:OLD.pb_id;
end if;
end;
Also you can see work of this trigger in action on SQL Fiddle.
I have been bogged in this problem for quite a long time....Can anyone help me out?
Here is the thing I want to implement:
I have a table A, A has attributes: id, count, total. Here I am required to implement such a trigger: IF the count in table A is updated, the trigger will set the total to 1.
My initial code is like this:
CREATE OR REPLACE TRIGGER tri_A AFTER UPDATE OF count ON A
FOR EACH ROW
BEGIN
UPDATE A SET total = 1 WHERE id = :new.id;
END;
/
The problem with this is the mutating table. When the table is updated, the table will be locked. I searched for the answers, I tried pragma autonomous_transaction, but I got an invalid trigger specification error. And there are other comments saying that we should try to use a combination of triggers to do this....I can't figure out how to do this
Assuming id is the primary key, you don't want to UPDATE the table. You just want to set :new.total. You'll also need to do this in a BEFORE UPDATE trigger not an AFTER UPDATE trigger.
CREATE OR REPLACE TRIGGER tri_A
BEFORE UPDATE OF count ON A
FOR EACH ROW
BEGIN
:new.total := 1;
END;
I have two Tables.
I want to insert the same record on both tables at the same time.
I.e., while I insert a record for the first table, this same record also is inserted in the second table using a trigger.
Do you have any experience/advice in this process ?
if you're using stored procedures you can easily manage this
CREATE PROCEDURE sp_Insert
#Value varchar(10)
AS
insert into table1 (...,...) values (#value,...)
insert into table2 (...,...) values (#value,...)
I would suggest using Erik's method over a trigger. Triggers tend to cause performance issues, and a lot of times, you forget that the trigger exists, and get unexpected behavior. If you do want to use a trigger however, it will work. here is an example:
CREATE TRIGGER trgTest ON Test
FOR INSERT
AS
INSERT Test2
(Id, value)
SELECT Id, Value
FROM Inserted
Can Use Cursor Concept!
CREATE OR REPLACE TRIGGER bi_order
BEFORE INSERT
ON ord
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
WHEN (NEW.payment_type = 'CREDIT')
DECLARE
CURSOR cur_check_customer IS
SELECT 'x'
FROM customer
WHERE customer_id = :NEW.customer_id
AND credit_rating = 'POOR';
lv_temp_txt VARCHAR2(1);
lv_poor_credit_excep EXCEPTION;
BEGIN
OPEN cur_check_customer;
FETCH cur_check_customer INTO lv_temp_txt;
IF (cur_check_customer%FOUND) THEN
CLOSE cur_check_customer;
RAISE lv_poor_credit_excep;
ELSE
CLOSE cur_check_customer;
END IF;
EXCEPTION
WHEN lv_poor_credit_excep THEN
RAISE_APPLICATION_ERROR(-20111, 'Cannot process CREDIT ' ||
'order for a customer with a POOR credit rating.');
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20122, 'Unhandled error occurred in' ||
' BI_ORDER trigger for order#:' || TO_CHAR(:NEW.ORDER_ID));
END bi_order;