Oracle invalid trigger ORA-04098 - sql

I cannot figure out where is the problem. here is my trigger
my produkt table has attributes: produktid, name, manufacturing_price, sale_price
i am trying to make sale price 1.1 value of manu price
CREATE OR REPLACE TRIGGER "predajna_cena"
AFTER update of "MANUFACTURING_PRICE" on "PRODUKT"
begin
UPDATE PRODUKT SET SALE_PRICE = MANUFACTURING_PRICE*1.1;
end;
/
ALTER TRIGGER "predajna_cena" ENABLE;
apex is showing Object Status INVALID
and i cannot change manufacturing price
error ORA-04098: trigger ' ' is invalid and failed re-validation
thanks

CREATE OR REPLACE TRIGGER "predajna_cena"
AFTER update of "MANUFACTURING_PRICE" on "PRODUKT"
begin
UPDATE PRODUKT SET SALE_PRICE = MANUFACTURING_PRICE*1.1;
end;
/
If you were able to make this trigger to work, it will update all prices after each and every update of the table "PRODUKT". Probably not what you want.
For such case, you should use a BEFORE UPDATE ... FOR EACH ROW trigger, changing the product price before inserting it :NEW."SALE_PRICE" = :NEW."MANUFACTURING_PRICE"*1.1.
Something like that maybe:
CREATE OR REPLACE TRIGGER "predajna_cena"
BEFORE UPDATE OF "MANUFACTURING_PRICE" ON "PRODUKT"
FOR EACH ROW
BEGIN
:NEW.SET SALE_PRICE := :NEW.MANUFACTURING_PRICE*1.1;
END;
Untested. Beware of typos!
Depending your needs an other option would use a virtual column instead of a trigger to achieve the same result.
DROP TRIGGER "predajna_cena";
ALTER TABLE "PRODUKT" DROP COLUMN "MANUFACTURING_PRICE";
ALTER TABLE "PRODUKT" ADD "MANUFACTURING_PRICE"
GENERATED ALWAYS AS ("SALE_PRICE" * 1.1) VIRTUAL;
Untested. Beware of typos!

Related

trigger to update specific column when insert/update happened in same table

I trying to write a trigger that will update a column when user insert or updates a row, within the same table.
Example:
insert into user(ID, F_NM, L_NM, EMAIL) values ('1', 'John','Doe','john.doe#market.org.com');
after the insert, i want to call: update user set ORG = 'market' where ID = '1'.
create or replace trigger user_change
after insert or update of EMAIL on USER
for each row
declare
NEW_ORG VARCHAR(10);
BEGIN
CASE
when :NEW.EMAIL like '$#market.org.com' then
NEW_ORG := 'market';
........
END CASE;
UPDATE USER set ORG = NEW_ORG where ID = :NEW.ID
END;
Calculating the new ORG work, but I can't get the update statement to work.
I get 'ORA-04091 table USER is mutating, trigger/funtion may not see it', figure its due to me inserting/updating the same record at same time. Tried adding 'pragma autonomous_transaction' and 'commit' to the trigger, the insert/update of fields works but the ORG does not get updated.
Also tried changing to INSTEAD OF INSERT OR UPDATE OF EMAIL but I keep getting 'ORA-04073 column list not valid for this trigger type'
create or replace trigger user_change
instead of insert or update of EMAIL on USER
while i get 'ORA-25002 cannot create instead of triggers on tables'
create or replace trigger user_change
instead of insert on USER
Why not simply turn the trigger to a before trigger, when you can set the value before it is written? This way, you don't need to run a new DML statement on the table, which avoid the "mutating" error.
create or replace trigger user_change
after insert or update of email on user
for each row
begin
if :new.email like '%#market.org.com' then
:new.org := 'market';
end if;
end;
Looks like your org column can be calculated virtual column. In this case it would be better to create user-defined deterministic pl/sql function that returns correct calculated value and add it to your table, for example:
Alter table t add org varchar2(30) generated always as (f_get_org(email))

ORACLE SQL trigger and SUM()

I have a table COMMANDE and a table REGROUPE. I have that function:
CREATE OR REPLACE PROCEDURE multiplicateur(a NUMBER, taxes NUMBER, c OUT NUMBER)
IS
BEGIN
c := a * taxes ;
END multiplicateur;
/
I'm trying to make a trigger using that founction to update a total price with taxes from a command that can contain more than one item. I tried this but it doesn't want to work:
create or replace TRIGGER MAJ_PRIX_COMMANDE
AFTER INSERT OR UPDATE OR DELETE ON REGROUPE
FOR EACH ROW
DECLARE
resultat NUMBER;
BEGIN
UPDATE COMMANDE
SET COMMANDE.prixTotal = multiplicateur((CAST((SELECT SUM(prixRegroupe)FROM REGROUPE WHERE REGROUPE.numCommande = :NEW.numCommande)AS NUMBER)),1.15,resultat)
WHERE COMMANDE.numCommande = :NEW.numCommande;
END;
Can someone help me?
How about this? I sent this from my iPhone; this code hasn't been tested.
create or replace TRIGGER MAJ_PRIX_COMMANDE
AFTER INSERT OR UPDATE OR DELETE ON REGROUPE
FOR EACH ROW
DECLARE
resultat NUMBER;
l_groupe NUMBER; --will store sum based on numCommande
BEGIN
--retrieve sum of prixRegroupe
SELECT SUM(r.prixRegroupe)
INTO l_groupe
FROM regroupe r
WHERE r.numCommande = :NEW.numCommande;
--call procedure and pass the sum of priRegroupe
multiplicateur(l_groupe, 1.15, resultat);
--use precedures out argument to update commande
UPDATE COMMANDE c
SET c.prixTotal = resultat
WHERE c.numCommande = :NEW.numCommande;
END;
This code won't work. It will result in a mutating trigger error. Within a trigger you cannot query or modify the same table that the trigger is based on until after the trigger has completed execution.
ORA-04091: table name is mutating, trigger/function may not see it
Your problem right now is that you're querying the regroupe table while the trigger is trying to insert/update the same table. This cannot be accomplished.
You'll need to find a way to get the sum of the prixRegroup column some other way. It's late if I think of anything I'll respond tomorrow.

Oracle Sql trigger before update of column

I want to create an update trigger for a table called purchases that will update the total cost field and also log a record in the purchases log table to indicate which purchase was updated.
I don't have much experience with creating triggers but so far this is what i've got
CREATE OR REPLACE TRIGGER Update_Purchase_Audit BEFORE
UPDATE ON Purchases
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
WHEN(NEW.p_id>0)
DECLARE total_cost INTEGER;
BEGIN
set total_cost := (:NEW.quantity * :NEW.unitcost);
:NEW.total_cost:=total_cost*0.165;
INSERT INTO Purchase_Log(eventdate, p_id, descrip)
VALUES(SYSDATE, :NEW.p_id, :NEW.product);
END;
/
I get this error when creating the trigger:
trigger created with compilation errors. When I run show errors; I get ORA-00922: missing or invalid option
Any suggestion? Thanks
CREATE OR REPLACE TRIGGER Update_Purchase_Audit
BEFORE UPDATE ON Purchases
FOR EACH ROW
WHEN (NEW.p_id > 0)
DECLARE
total_cost number;
BEGIN
total_cost := :NEW.quantity * :NEW.unitcost;
:NEW.total_cost := total_cost * 0.165; --<< this is ok BEFORE update
-->> Do you have table relations here? THis may need to go AFTER update
-- in separate trigger
INSERT INTO Purchase_Log (eventdate, p_id, descrip)
VALUES(SYSDATE, :NEW.p_id, :NEW.product);
END;
/

Create Trigger to reorder a column and modify statement levels

I need to Alter the Product table to have a varchar2(3) reorder column and modify the statement level trigger from the notes to set the product reorder field to “yes” if the quantity on hand is less than twice the product min quantity or if the quantity on hand is less than 10. The value should be “no” otherwise. The trigger is fired after an insert or an update to p_min or p_qoh. Debug by checking the data beforehand, making a change, then checking afterwards.
For this I have
CREATE or REPLACE TRIGGER
TRG_Product_Reorder
AFTER INSERT OR UPDATE of P_min, P_qoh ON lab9_Product
BEGIN
UPDATE lab9_Product SET REORDER = 'yes'
WHERE P_qoh < P_min*2 or p_qoh < 10;
UPDATE lab9_Product SET REORDER = 'no'
WHERE P_qoh >= p_min*2;
END;
/
I get the error:
SQL statement ignored
"REORDER": invalid identifier
I think you might want a before trigger rather than an after trigger. It would be something like this:
CREATE or REPLACE TRIGGER
TRG_Product_Reorder
BEFORE INSERT OR UPDATE of P_min, P_qoh ON
lab9_Product
BEGIN
IF :OLD.P_qoh < :OLD.P_min*2 AND :OLD.p_qoh < 10 THEN
:NEW.REORDER := 'yes';
ELSE :NEW.REORDER := 'no';
END IF;
END;

Oracle SQL trigger for automatically set a column value

I am writing a Oracle trigger. This trigger should automatically set the value of the column "productId" to be the oid of the row just inserted.
The trigger I wrote is:
create or replace trigger MyProduct_id_trg
after insert on MyProduct
begin
update MyProduct set productId = inserted.oid where oid = inserted.oid;
end;
However, this does not work.
Can someone help me with this?
Regards.
Looks like you are trying to use SQL Server syntax on an Oracle database! Try this:
create or replace trigger MyProduct_id_trg
before insert on MyProduct
for each row
begin
:new.productId := :new.oid;
end;
(Note: before not after, and with for each row.)