I have this table that represents a weak entity and is a typical table for introducing items ordered:
insert into ITEM_FORNECIMENTO values (a_orderId,a_prodId,a_prodQtd, a_buyPrice);
I want my trigger to update the last column (the total price of products WITHOUT iva) to do this : totalPrice= totalPrice*(1+(iva/100), each time I insert or update an entry on that table.
so, I came up with this, but I'm totally wrong when it comes to work with new and old values.
create or replace
trigger t_replaceTotal
after insert or update of id_prod,qtd_if,prec_total_if on item_fornecimento
for each row
declare
iva produto.iva_prod%type;
idProd produto.id_prod%type;
r_old item_fornecimento.prec_total_if%type:=null;
r_new item_fornecimento.prec_total_if%type:=null;
begin
select iva_prod,id_prod into iva,idprod from produto p where p.id_prod = id_prod;
r_old:= :old.prec_total_if;
r_new:= :new.prec_total_if;
update item_fornecimento item set prec_total_if = r_old * (1+(iva/100)) where item.id_prod = idprod;
end;
Could someone please help rewriting this code? I'm getting the error: ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "FUSION.T_REPLACETOTAL", line 8
ORA-04088: error during execution of trigger 'FUSION.T_REPLACETOTAL'
The problem is that you are trying to fetch every row from the table because you are matching a column (id_prod) to itself. I suspect you want to use :new.id_prod or :old.id_prod.
select .... from produto p where p.id_prod = id_prod;
Next, make this a BEFORE INSERT/UPDATE trigger and replace the UPDATE statement with
:new.prec_total_if := r_old * (1+(iva/100));
Otherwise you'll get a mess of mutating table errors.
That error is telling you that a query that saves its result into a variable is returning more than one result. As such it doesn't know what you want to save in the variable.
Try running the following:
select iva_prod,id_prod from produto p where p.id_prod = id_prod;
and I bet it will give you more than one result, which it can't save into iva,idprod.
Related
I have a trigger set to fire after an update of a specific column. I want to update the value of a specific column after a specific value from another column changes to another specific value.
I'm getting the errors:
ORA-04091: table tableName is mutating, trigger/function may not see it
ORA-06512: at "triggerName", line 14
ORA-04088: error during execution of trigger 'triggerName'
I've rewritten this as a before update and after update, as well as tried storing the logic in a function, and using "pragma autonomous_transaction", but the error still gets thrown.
BEFORE update of columnName1 ON tableName
FOR EACH ROW
BEGIN
if :new.columnName1 = 3 AND :old.columnName1 = 1 then
update tablename
set columnName2= MOD(sequenceName.NextVal, 5) + 1
where tableName.columnName2 = :old.columnName2;
end if;
END;
/
I don't understand why the entire table is labelled as "mutating" when I am not updating the column affected by the update the trigger is responding to. Surely, you should be able to update the value of a column in a table if another value in the table changes, or am I crazy here?
Note: Only one entry would be affected at a time. In my application logic, I update the status of some person in the database. I want the database to do some logic only on a specific status change, and I want to avoid using API calls for the logic here, as you can see, it is simply one line of logic in PLSQL.
Thanks
Perhaps you don't really want to update the table but just change a value in the specific row being updated.
If so, eschew the update and just set the value:
BEFORE update of columnName1 ON tableName
FOR EACH ROW
BEGIN
if :new.columnName1 = 3 AND :old.columnName1 = 1 then
:new.columnName2 := MOD(sequenceName.NextVal, 5) + 1 ;
end if;
END;
CREATE TRIGGER Alerta_Trig
BEFORE INSERT OR UPDATE OF Valor ON Medicao
FOR EACH ROW
WHEN (NEW.VALOR > 40)
BEGIN
UPDATE SENSOR
SET ALERTA = 'Alerta laranja'
WHERE SENSOR_ID=(SELECT SENSOR_SENSOR_ID FROM MEDICAO);
END;
I have this table of Sensors that are supposed to receive a String with an alert if 1 value > 40 enters the Medicao table. Any thoughs?
As you haven't said quite what is wrong I'm speculating a bit, but I can see two immediate potential problems.
You shouldn't query the same table again, generally, as you'll risk get a mutating table error. You also have no condition in the subquery so you'd be likely to get multiple rows back, and a subquery-returns-more-than-one-row error.
Presumably you're doing that subquery to try to get the ID value from the affected row, so use the :NEW pseudo-row for that:
CREATE TRIGGER Alerta_Trig
BEFORE INSERT OR UPDATE OF Valor ON Medicao
FOR EACH ROW
WHEN (NEW.VALOR > 40)
BEGIN
UPDATE SENSOR
SET ALERTA = 'Alerta laranja'
WHERE SENSOR_ID = :NEW.SENSOR_SENSOR_ID;
END;
I am having an issue with a trigger. After I add the trigger to my database, when I try to insert a row that the trigger will act on, I get a mutating table error. I don't know how to avoid this. Would someone mind looking at this and tell me what I am doing wrong, and how to rewrite it?
CREATE OR REPLACE TRIGGER ORNG_INV_LINE_TOTAL_TRIGGER
FOR INSERT OR UPDATE ON ORNG_INV_LINE
COMPOUND TRIGGER
AFTER EACH ROW IS
BEGIN
UPDATE ORNG_INVOICE SET Inv_Amount = (SELECT SUM(ORNG_INV_LINE.Inv_Line_Total)
FROM ORNG_INV_LINE
WHERE ORNG_INVOICE.INV_Num = :NEW.INV_Num);
END AFTER EACH ROW;
END ORNG_INV_LINE_TOTAL_TRIGGER;
/
I'm not sure why it is triggering an error. I'm trying to do the action after the update. All I want to do is get the sum for all of the lines of all matching invoice numbers, and write that value in the INVOICE table. Thanks for the help.
Your trigger is written on the table ORNG_INV_LINE for insert or update and again you made a select on the same table while updating ORNG_INVOICE table so trigger is mutating,
to over come this you have to use statement level trigger instead of row level trigger .
i.e after each statement should be there in code instead of after each row.
This can help you.
Here is the solution...apparently everyone is busy with Thanksgiving. Hopefully this helps the next guy.
create or replace TRIGGER ORNG_INV_L_TTL_TRIG
AFTER INSERT OR UPDATE OR DELETE ON ORNG_INV_LINE
BEGIN
UPDATE ORNG_INVOICE SET Inv_Amount = (SELECT SUM(Inv_Line_Total)
FROM ORNG_INV_LINE
WHERE INV_Num = ORNG_INVOICE.INV_Num);
END ORNG_INV_L_TTL_TRIG;
/
I'm creating a row-level trigger for Oracle using SQL Tools. I will attach a picture of the ERD I am working off of. I will also include my instructions, paste what code I have tried, and the error I am getting.
Description of request:
Create a row-level trigger named "TRG_USED_COST" on the USED table. The trigger should execute BEFORE a new row is inserted in the table. The insert command will provide a value for "CHEM_NUM","JOB_NUM", and "USED_QTY" that are being added to the table. Using the CHEM_NUM being used in the insert, retrieve the "CHEM_UNIT_COST" from the CHEMICAL table. Multiply the chemical unit cost times the quantity of chemicals used in this row, and include that value as the "USED_CHARGE" for the row being inserted.
My code:
CREATE OR REPLACE TRIGGER TRG_USED_COST
BEFORE INSERT OR UPDATE OF CHEM_NUM,JOB_NUM,USED_QTY ON USED
FOR EACH ROW
BEGIN
UPDATE USED
SET USED_CHARGE = CHEM_UNIT_COST * USED_QTY
WHERE CHEM_NUM IS NOT NULL;
END;
/
After I enter the code, I receive the error:
PL/SQL: ORA-00904: "CHEM_UNIT_COST": invalid identifier
I know that I'm getting the error because I did not reference the CHEMICAL table that "CHEM_UNIT_COST" is located in...but I don't know how to reference it.
You have several issues here. First, you do not "update" the target table in this case. Use the :new attribute on the trigger. Then select the cost from the other table.
CREATE OR REPLACE TRIGGER TRG_USED_COST
BEFORE INSERT OR UPDATE OF CHEM_NUM,JOB_NUM,USED_QTY ON USED
FOR EACH ROW
DECLARE
v_cost CHEMICAL.CHEM_UNIT_COST%TYPE;
BEGIN
SELECT CHEM_UNIT_COST
INTO v_cost
FROM CHEMICAL
WHERE CHEM_NUM = :new.CHEM_NUM;
:new.USED_CHARGE := v_cost * :new.USED_QTY;
END;
/
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;