Update trigger updating all rows in a table - oracle

I have a trigger I need to write to update a row to 'F' in a table called StudentGrades (which contains student_id, section_id, and grade) to fire when a student's status is changed to 'I' in a different table called student. My problem is I thought it worked, but it'll update all the values to 'F' no matter what the status is updated to and it updates the grades for all the student_id's in the table. Here's my code:
create or replace NONEDITIONABLE TRIGGER grades_trigger
AFTER UPDATE ON STUDENT
FOR EACH ROW
BEGIN
UPDATE StudentGRADES
SET GRADE = 'F'
WHERE :NEW.STATUS= 'I';
END ;
I can post more if I need to.
Thanks.

If I understood you correctly, that would be
create or replace noneditionable trigger grades_trigger
after update on student
for each row
begin
if :new.status= 'I' then --> is student's status changed to I?
update studentgrades set --> yes, it is - so - update another table ...
grade = 'F'
where student_id = :new.student_id; --> but not for ALL students - only for the one for which the trigger had fired
end if;
end;

Related

Create trigger that updates row depending on column value from other table

I would like to create a trigger that updates a row in a table (TABLE2) depending on column value from other table (TABLE1).
Which line must be updated depends on the ID of TBL1.
CREATE OR REPLACE TRIGGER INSERT_PAGE
BEFORE UPDATE OR INSERT
ON TABLE1
FOR EACH ROW
BEGIN
IF INSERTING THEN
INSERT INTO TABLE2 (TBL1ID,STEP,PAGE) VALUES
(:NEW.TBL1ID,:NEW.STEP,15);
ELSIF UPDATING and :NEW.STATE='APPROVED' THEN
UPDATE TABLE2
SET PAGE=16 AND STEP1='TEXT123'
WHERE TBL1ID =TABLE1.TBL1ID;
END IF;
END;
Can someone help me in creating a trigger with an update statement?
Would this be as well a good way to go?
So I have two tables, the column state in table1 is changing throughtout the process.
Depending on the change of the column state from table1, I want to change or better say update the row in table 2 and set some columns like PAGE and STATE in Table 2 depending on column value STATE in Table 1.
I do not want that a new row being created each time TABLE 1 gets updated, only the corresponding row should be updated.
As far as I understood is you want to update table2 only when the state in table1 changed to 'approved' for a row and if a row is inserted in table1 trigger will insert the row in table2.
I have made some corrections to your code. Let me know if it is not what you wanted.
CREATE OR REPLACE TRIGGER INSERT_PAGE
BEFORE UPDATE OR INSERT
ON TABLE1
FOR EACH ROW
DECLARE
BEGIN
IF INSERTING THEN
INSERT INTO TABLE2 (TBL1ID,STEP,PAGE) VALUES
(:NEW.TBL1ID,:NEW.STEP,15);
ELSIF UPDATING THEN
IF :NEW.STATE = 'APPROVED' THEN
UPDATE table2 t2 SET
STATE = :NEW.STATE, PAGE=16, STEP1='TEXT123'
WHERE t2.TBL1ID = :OLD.TBL1ID;
END IF;
END IF;
END;

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.

After Insert Trigger to modify one column and update newly inserted row values in Oracle

/* Formatted on 24/09/2015 09:36:39 (QP5 v5.215.12089.38647) */
CREATE OR REPLACE TRIGGER TR_student_PREF_sub_UPDATE
AFTER INSERT OR UPDATE
ON student
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
v_preferred_sub_value NUMBER (1);
no_project_record EXCEPTION;
BEGIN
IF UPDATING OR INSERTING
THEN
IF (:NEW.is_sub = 0 AND :NEW.standard_id IS NOT NULL)
THEN
SELECT preferred_sub
INTO v_preferred_sub_value
FROM STANDARD
WHERE standard_id = :NEW.standard_id;
ELSIF (:NEW.is_sub = 1 AND :NEW.subject_id IS NOT NULL)
THEN
SELECT preferred_sub
INTO v_preferred_sub_value
FROM admin_subject.source
WHERE source_id = :NEW.subject_id;
END IF; /* v_preferred_sub_value IS NOT NULL THEN UPDATE preferred_sub VALUE IN student TABLE */
IF (v_preferred_sub_value IS NOT NULL)
THEN
UPDATE student
SET preferred_sub = v_preferred_sub_value
WHERE student_id = :NEW.student_id;
COMMIT;
END IF;
END IF;
EXCEPTION
WHEN NO_PROJECT_RECORD
THEN
NULL;
END TR_student_PREF_sub_UPDATE;
Process : When the user click save action from UI, this invoke insert method in java code. While inserting values into subject table, trigger called and checking is_sub value if 0 then fetching preferred_sub value from standard table. If the is_sub = 1 then fetching preferred_sub from admin_subject.source schema table.
Based on v_preferred_sub_value it is trying to update subject table which was newly inserted row.
I ran the insert action from UI, after the trigger called, i checked the subject table with preferred_sub column it shows null value.
Please help me, what i made the mistake over there.
student table have student_id, subject_id, standard_id and is_sub values and more.
standard table & student table are in same schema.
source is different schema which has grant all privileged.
Change your trigger to a before trigger and assign the determined values to the appriopriate :new pseudo column. The database will take care of the rest.
IF (v_preferred_sub_value IS NOT NULL)
THEN
:NEW.preferred_sub = v_preferred_sub_value;
END IF;
The value of :NEW.preferred_sub will now be placed in the table record.

Trigger in oracle. Update field when insert or update another field

I need To update the field DATAMARKER"of my table LOG_ALARMA when I have one INSTER or UPDATE of "CONTADOR".
i have this, but return muting error.
create or replace TRIGGER TRIGGER2
AFTER INSERT OR UPDATE OF CONTADOR ON LOG_ALARMA
for each row
BEGIN
UPDATE LOG_ALARMA a
SET a.DATAMARKER=(SYSDATE);
END;
I look another examples and they work but i can't execute this correctly.
IF i comment the line for each row in my trigger body then it is working fine but it UPDATES all the rows in my table.
You do not issue an update SQL statement, because that would again cause the trigger to fire.
Instead, you just set the value :new.DATAMARKER to sysdate, using PL/SQL not SQL.
Make it a BEFORE INSERT OR UPDATE also.
CREATE TABLE Mutating
(
ID1 NUMBER,
DATE1 DATE
)
data present in a table is
ID1 DATE1
1 09/01/2015 14:09:14
1 08/31/2015 14:09:21
2 08/30/2015 14:09:30
Now i want to update the date1 if any update happens on id1 column in that situation i have used trigger look below.
CREATE OR REPLACE TRIGGER Mutating_trg
before INSERT OR DELETE OR UPDATE ON Mutating
referencing old as old new as new
for each row
begin
if updating then
:new.date1:=sysdate;
end if;
end;
then i have issued update statement
update set Mutating id1=6 where trunc(date1)=trunc(sysdate-2)
1 row updated
Now look into results
ID1 DATE1
1 09/01/2015 14:09:14
6 09/02/2015 14:09:14
2 08/30/2015 14:09:30
You should use before statement.

TRIGGER Oracle to prevent updating or inserting

I am having problems with this code below, which is a trigger used in Oracle SQL:
CREATE OR REPLACE TRIGGER TRG_TUTOR_BLOCK
BEFORE INSERT OR UPDATE ON tutors
FOR EACH ROW
DECLARE
BEGIN
IF :new.tutorName = :old.tutorName
THEN
RAISE_APPLICATION_ERROR(-20101, 'A tutor with the same name currently exists.');
ROLLBACK;
END IF;
END;
/
This trigger is used to prevent users from entering the same tutor name at different records.
After I insert two records with the same tutorname, the trigger does not block me from inserting it. Is there anyone can tell me what are the problems with this coding? Here are the sample format and insert values:
INSERT INTO tutors VALUES (tutorID, tutorName tutorPhone, tutorAddress, tutorRoom, loginID);
INSERT INTO tutors VALUES ('13SAS01273', 'Tian Wei Hao', '019-8611123','No91, Jalan Wangsa Mega 2, 53100 KL', 'A302', 'TianWH');
Trigger in Kamil's example will throw ORA-04091, you can see this with your own eyes here. ROLLBACK in a trigger is unnecessary, it runs implicitly when a trigger makes a statement to fail.
You can prohibit any DML on table by altering it with read only clause:
alter table tutors read only;
At last, integrity should be declarated with integrity constraints and not with triggers.
Good luck!
You don't need a trigger for this in Oracle.
You can do it with an "unique index" on the tutorName column (see http://docs.oracle.com/cd/B28359_01/server.111/b28310/indexes003.htm#i1106547).
Note: about your trigger, it fails on checking for another record with the same tutorName because it's not scanning the tutors table for another record with the same tutorName, it's just comparing the tutorName values of the row you are creating (in this case, old.tutorName is just NULL, because the row doesn't exist yet).
Check the case in yours trigger body
IF :new.tutorName = :old.tutorName
It returns true only if 'tutorName' value is the same in new and old record. When you'll trying to updat some value you'll get
IF 'someTutorName' = 'someTutorName'
which will return TRUE.
Inserting row cannot fire this rule because you're trying to compare something like that:
'someTutorName' = NULL
This case always returns FALSE.
Try to use something like that
CREATE OR REPLACE TRIGGER TRG_TUTOR_BLOCK
BEFORE INSERT OR UPDATE ON tutors
FOR EACH ROW
DECLARE
rowsCount INTEGER;
BEGIN
SELECT COUNT(*) FROM tutors WHERE tutorName is :new.tutorName INTO rowsCount;
IF rowsCount > 0
THEN
RAISE_APPLICATION_ERROR(-20101, 'A tutor with the same name currently exists.');
ROLLBACK;
END IF;
END;
/
But the best solution is the one mentioned by friol - use unique index by executing SQL like this
ALTER TABLE tutors
ADD CONSTRAINT UNIQUE_TUTOR_NAME UNIQUE (tutorName);
If you wanna completely ignore recording a row to a table you can follow these steps
rename table to something else and create a view with the same name and create an instead of trigger.
create table usermessages (id number(10) not null)
GO
alter table usermessages rename to xusermessages
GO
create or replace view usermessages as (select * from xusermessages)
GO
create or replace trigger usermessages_instead_of_trg
instead of insert or update on usermessages
for each row
begin
Null ;
end ;
GO
insert into usermessages(123)
Live test available here below
http://sqlfiddle.com/#!4/ad6bc/2

Resources