How to create trigger that transfer data from one table to another tabke - oracle

How to create Trigger that transfer the sum of multiple rows to another table, i have two column qty and prise i want to transfer the sum of multiple rows to another table ex supplier

Not tested but you need to try something like this..your question is missing test data and also table information so i did understand what do you mean by adding sum of multiple rows...but this might give you an idea:
CREATE OR REPLACE TRIGGER TG_NAME
AFTER INSERT ON supplier
FOR EACH ROW
DECLARE
CURSOR cur_name IS
SELECT SUM (qty + price) sum_rows
FROM purchasing;
vRowStudent cur_name%ROWTYPE;
BEGIN
OPEN cur_name;
FETCH cur_name INTO vRowStudent;
CLOSE cur_name;
INSERT INTO supplier
(sup_column)
VALUES (vRowStudent.sum_rows);
END TG_NAME;

Related

Trigger of two tables in an audit

Good morning, I am trying to audit two tables, and I have investigated that it cannot be done, therefore I explain what I wanted to do:
I have two tables (Participante, Actividad) which are joined by a third table (Part_Actividad)
I want to audit the Participants table, but in the same way I need the Id of the activity to know in which activity the data of a participant is changed.
Ideas I had
Create a trigger like the following
CREATE OR REPLACE TRIGGER Tri_Auditoria
AFTER INSERT ON Participante
FOR EACH ROW
DECLARE
v_Participante_ID Participante.Participante_ID%TYPE;
v_Actividad_ID Part_Actividad.Actividad_ID%TYPE;
BEGIN
SELECT participante_ID INTO v_Participante_ID
FROM Participante;
SELECT Actividad_ID INTO v_Actividad_ID
FROM Part_Actividad
WHERE PartAct_ID = v_Participante_ID;
INSERT INTO Auditoria(Auditoria_ID, Actividad_ID, Participante_ID, TipPart_ID_Ant, Part_P_Nombre_Ant, Part_P_Apell_Ant, Part_Cedula_Ant, Part_Genero_ant, Part_FNaci_Ant, Aud_Operacion, Usuario_Modificador, Fecha_Modificacion)
VALUES (sec_Auditoria.nextval, v_Actividad_ID, :new.Participante_ID,:new.TipPart_ID,:new.Part_P_Nom,:new.Part_P_Apell,:new.Part_Cedula,:new.Part_Genero,:new.Part_FNaci,'I',USER,sysdate);
END Tri_Auditoria;
/
Result:
When I insert data into the participante table, it is not inserted and it sends a trigger error.
Mutating table error, isn't it? That's because you're selecting from the same table which caused trigger to fire, and that's not allowed.
Anyway, you shouldn't do that because you have that value in disposal - just reference it using the :new pseudorecord, such as
CREATE OR REPLACE TRIGGER Tri_Auditoria
AFTER INSERT ON Participante
FOR EACH ROW
DECLARE
v_Actividad_ID Part_Actividad.Actividad_ID%TYPE;
BEGIN
SELECT Actividad_ID
INTO v_Actividad_ID
FROM Part_Actividad
WHERE PartAct_ID = :new.participante_ID; --> this
INSERT INTO Auditoria
(Auditoria_ID, Actividad_ID, Participante_ID,
TipPart_ID_Ant, Part_P_Nombre_Ant, Part_P_Apell_Ant,
Part_Cedula_Ant, Part_Genero_ant, Part_FNaci_Ant,
Aud_Operacion, Usuario_Modificador, Fecha_Modificacion)
VALUES (sec_Auditoria.nextval, v_Actividad_ID, :new.Participante_ID,
:new.TipPart_ID,:new.Part_P_Nom,:new.Part_P_Apell,
:new.Part_Cedula,:new.Part_Genero,:new.Part_FNaci,
'I',USER,sysdate);
END Tri_Auditoria;
/

How to create TRIGGER with a reference to the triggered table?

Can I create an AFTER TRIGGER on a table and using that table in my SELECT query without getting mutating table error?
Example to a query I want to use.
This query will update number of times a certain status name is showing up in alert life cycle:
CREATE OR REPLACE TRIGGER COUNT_STEP
AFTER INSERT
ON STEPS
FOR EACH ROW
DECLARE
V_COUNT_SETP VARCHAR (10000);
BEGIN
SELECT COUNT (STATUS_NAME)
INTO V_COUNT_SETP
FROM (SELECT A.ALERT_ID, S.STATUS_NAME
FROM ALERTS A, ALERT_STATUSES S, STEPS ST
WHERE :NEW.ALERT_INTERNAL_ID = A.ALERT_INTERNAL_ID
AND ST.ALERT_STATUS_INTERNAL_ID = S.STATUS_INTERNAL_ID
AND S.STATUS_NAME IN ('Auto Escalate'))
GROUP BY ALERT_ID;
UPDATE ALERTS A
SET A.COUNT = V_COUNT_ESC
WHERE A.ALERT_INTERNAL_ID = :NEW.ALERT_INTERNAL_ID;
END;
/
The table I'm inserting a record to is also needed for counting the number of step occurrences since it's stores the alert id and all the steps id it had.
You need to be a bit more clearer in your questions. But, from what i understood, you need to create a trigger on a table, and perform a select for that same table. That gives you a mutanting table error. To bypass that, you need to perform a compound trigger on that table. Something like this:
create or replace trigger emp_ct
for insert on employees compound trigger
v_count number; -- Add variable here
before statement is
begin
-- PERFORM YOUR SELECT AND SEND TO A VARIABLE
end before statement;
after each row is
begin
-- DO WANT YOU WANTED TO DO. USE THE VARIABLE
end after each row;
end;
basically, with a compound trigger, you can capture every trigger event. By doing that, allows to query the table you're capturing.

Inserting Record Type

I have a source table, and a history table. They are identical, except the history table has a notes column as the last column.
The table is large, 55 columns, which I do not want to list all the columns. We do not want to use a trigger on this, but just create the history entry in the code itself.
If I simply do an INSERT INTO <history> SELECT * FROM <source> WHERE...... I will get "not enough values".
I'm hoping to do something of this nature: (Note this is just an anonymous block)
DECLARE
v_old_rec company_table%ROWTYPE;
BEGIN
SELECT * INTO v_old_rec
FROM company_table
WHERE company_id = 32789;
INSERT INTO company_table_hist
VALUES v_old_rec || ',MONTHLY UPDATE';
END;
Anything like this possible, so I do not have to list 55 columns?
Thank you.
It's quite simple actually:
INSERT INTO company_table_hist
(SELECT t.*, MONTHLY_UPD
FROM company_table t
WHERE company_id = 32789);
Of course monthly_upd must be bound somehow

Auditing a table with many columns without Fine Grained Auditing

I have to create a trigger for a table with many columns and I want to now if is any possibility to avoid using the name of the column after :new and :old. Instead of specifically use the column name I want to use the element from collection with column names of target table (the table on which the trigger is set).
The line 25 is that with the binding error:
DBMS_OUTPUT.PUT_LINE('Updating customer id'||col_name(i)||to_char(:new.col_name(i)));
Bellow you can see my trigger:
CREATE OR REPLACE TRIGGER TEST_TRG BEFORE
INSERT OR
UPDATE ON ITEMS REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW DECLARE TYPE col_list IS TABLE OF VARCHAR2(60);
col_name col_list := col_list();
total INTEGER;
counter INTEGER :=0;
BEGIN
SELECT COUNT(*)
INTO total
FROM user_tab_columns
WHERE table_name = 'ITEMS';
FOR rec IN
(SELECT column_name FROM user_tab_columns WHERE table_name = 'ITEMS'
)
LOOP
col_name.extend;
counter :=counter+1;
col_name(counter) := rec.column_name;
dbms_output.put_line(col_name(counter));
END LOOP;
dbms_output.put_line(TO_CHAR(total));
FOR i IN 1 .. col_name.count
LOOP
IF UPDATING(col_name(i)) THEN
DBMS_OUTPUT.PUT_LINE('Updating customer id'||col_name(i)||to_char(:new.col_name(i)));
END IF;
END LOOP;
END;
Sincerely,
After digging more I have found that is not possible to dynamically reference the :new.column_name or :old.column_name values in a trigger. Due to this I will use my code only to INSERT (it does not have an old value :-() and I will do some code in java to generate UPDATE statements.
I must refine my previous answer based on what has been said by Justin Cave and also my findings. We can create a dynamic list of values triggered by INSERTING and UPDATING, based on referencing clause (old and new). For example I have created 2 collections of type nested table with varchars. One collection will contain all column tabs, as strings, that I will use for auditing and another collection will contains values for that columns with binding reference (ex. :new.). After INSERTING predicate I have created a index by collection (an associative array) of strings with ID taken from list of strings with column tab name and the value taken from the list of values for that columns referenced by new. Due to the index by collection you have a full working dynamic list at your disposal. Good luck :-)

Triggers in Oracle PL/SQL Problems

I have just written a stored procedure and stored function that serve to insert a new row into my Orders table. The row update inserts: Ordernum, OrderDate, Customer, Rep, Manufacturer, Product, Qty, and SaleAmount.
I now have to write a trigger that updates my Salesreps table by adding the amount of the order just added. I am unsure of how to reference the rows. I have tried this:
CREATE OR REPLACE TRIGGER UpdateSalesrep
AFTER INSERT ON Orders
FOR EACH ROW
BEGIN
UPDATE Salesreps
SET Sales = Sales + :NEW.Amount
WHERE Rep = Salesrep;
End;
/
Sales is the name of the column on the Salesrep table. Amount if the name used in the stored proc. I am getting an error returned on 'Where Rep = Salesrep'. If I don't include this line, the trigger does not return any errors. However, I am assuming that if I can't figure out how to tie the sales amount into the one salesrep that made the sale, I will update every salesrep (which I'm sure they would be quite happy with). Any help would be greatly appreciated, as always.
CREATE OR REPLACE TRIGGER UpdateSalesrep
AFTER INSERT ON Orders
FOR EACH ROW
BEGIN
UPDATE Salesreps
SET Sales = Sales + :NEW.Amount
WHERE Salesrep = :NEW.Rep;
End;
/
Who have said that you have to write a trigger? Is this stated explicitly as a requirement in your homework task? You can also update table UpdateSalesRep in the same stored procedure that you have already written for inserting in table Orders.
Read: http://www.oracle.com/technetwork/issue-archive/2008/08-sep/o58asktom-101055.html

Resources