I have an After Insert trigger which is supposed to insert first, then do insert another table. But when any error occurs for inserting data in another table the all transaction terminated. I want to insert 1st data in base table whether the trigger fire successfully or not.
This is my code:
CREATE TRIGGER [dbo].[Insert_Teacher_Active_LC]
ON [dbo].[Teacher_Profile]
AFTER INSERT,UPDATE
AS
BEGIN
MERGE [ROSC].[dbo].[Active_LC] as d
USING (SELECT
DistrictID, upazilaID, LCID, LCVisitYr, Trimister,
CASE WHEN (TcrPres = 1 AND TcrMtchLCProf = 1)
THEN 1 ELSE 0
END AS TcrRpls
FROM INSERTED) AS s ON s.DistrictID = d.DistrictID
AND s.upazilaID = d.upazilaID
AND s.LCID = d.LCID
AND s.LCVisitYr = d.EduYr
WHEN MATCHED THEN
UPDATE
SET Trimister = s.Trimister, Tcr_Replace = s.TcrRpls
WHEN NOT MATCHED THEN
INSERT(DistrictID, UpazilaID, LCID, EduYr, Trimister, Tcr_Replace)
VALUES(DistrictID, UpazilaID, LCID, LCVisitYr, Trimister, TcrRpls);
-- Insert statements for trigger here
END
Related
I am trying to update an entry if already exists using a trigger. I would like to check if an entry exists update if not then insert. When I tried to insert new entry I got an error: 'Can't update table in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
DELIMITER //
CREATE TRIGGER check_table_before_insert BEFORE INSERT ON Songs FOR EACH ROW BEGIN IF NEW.PageURL =(
SELECT
Songs.PageURL
FROM
Songs
WHERE
Songs.PageURL = NEW.PageURL
) THEN
UPDATE
Songs
SET
Songs.Title = NEW.Title,
Songs.Album = NEW.Album,
Songs.Label = NEW.Label,
Songs.Release_Date = NEW.Release_Date,
Songs.PageURL = NEW.PageURL,
Songs.IsSingle = NEW.IsSingle,
Songs.Code = NEW.Code,
Songs.ImageURL = NEW.ImageURL,
Songs.Link_320 = NEW.Link_320,
Songs.Link_128 = NEW.Link_128,
Songs.Link_48 = NEW.Link_48,
Songs.AlbumURL = NEW.AlbumURL
WHERE
Songs.PageURL = NEW.PageURL;
END IF;
END;
// DELIMITER;
This isn't an appropriate use for a trigger.
If you want to perform a "insert or update" operation on a table, use the INSERT … ON DUPLICATE KEY UPDATE … syntax. It already has the semantics you are looking for.
If the columns you are updating amount to the entirety of the row, you may be able to use the REPLACE verb as an alternative to INSERT. Note that it will delete the row before insetting a new one, so any columns not included in the REPLACE query will be lost.
I am stuck in plsql , as I have making function in which I have to update a table if only values comes in select into ..
and if not come then not and if multiple comes then have to update and delete for all that values .
In below function if in first select into null value comes then should not goto exception handling should update only CUSTOMER table and only delete from table 3 ,, if one or many values comes then do all update and delete for each value
create or replace FUNCTION FUNCTION_NAME (
from_PARTICIPANT_KEY1 IN NUMBER
)
RETURN
IS
to_participant_key1 NUMBER (11);
BEGIN
SELECT to_participant_key
INTO to_participant_key1
FROM TABLE2
WHERE FROM_PARTICIPANT_KEY = from_PARTICIPANT_KEY1;
UPDATE CUSTOMERS C
SET C.CUSTOMER_STATUS_CD =
NVL (
(SELECT old_status_cd
FROM TABLE1
WHERE PARTICIPANT_UID = from_PARTICIPANT_KEY1
AND participant_cd = 'CUSTOMER'),
C.CUSTOMER_STATUS_CD
)
WHERE C.CUSTOMER_UID = from_PARTICIPANT_KEY1;
UPDATE subscribers C
SET C.STATUS_CD =
NVL (
(SELECT old_status_cd
FROM TABLE1
WHERE PARTICIPANT_UID = to_participant_key1
AND participant_cd = 'SUBSCRIBER'),
C.STATUS_CD
)
WHERE C.account_no = to_participant_key1;
DBMS_OUTPUT.PUT_LINE ('Delete TABLE1 rows');
DELETE FROM TABLE3
WHERE PARTICIPANT_UID = from_PARTICIPANT_KEY1 AND participant_cd = 'CUSTOMER';
DELETE FROM TABLE1
WHERE PARTICIPANT_UID = to_PARTICIPANT_KEY1 AND participant_cd = 'SUBSCRIBER';
COMMIT;
EXCEPTION -- exception handlers begin
WHEN NO_DATA_FOUND THEN -- handles 'division by zero' error
dbms_output.put_line('Customer not found ' || from_PARTICIPANT_KEY1);
WHEN OTHERS THEN -- handles all other errors
dbms_output.put_line('Some other kind of error occurred.');
END;
You can use BULK COLLECT INTO and iterate over collection.
First of all, you have to declare (or use some existing) collection type and create the variable of this type:
TYPE participant_keys is table of number (11);
l_participant_keys participant_keys;
Then, your query will change to:
SELECT to_participant_key
BULK COLLECT INTO to_participant_key1
FROM TABLE2
WHERE FROM_PARTICIPANT_KEY = from_PARTICIPANT_KEY1;
If the query will not return any record then you can check it with COUNT:
if l_participant_keys.COUNT = 0 then
-- update only CUSTOMER table and only delete from table 3
else
FOR I IN l_participant_keys.FIRST .. l_participant_keys.LAST LOOP
--use l_participant_keys(i) do all update and delete for each value
END LOOP;
end if;
I have 2 tables:
table 1 = SAMPLE_TABLE
table 2 = RESULT_TABLE (with proposed trigger)
I would like to use a trigger in RESULT table that, when a new record is inserted into into it, will update a field in SAMPLE table called, 'status' = "complete". The field 'status' to be updated in SAMPLE is related to RESULT by:
table 1 = SAMPLE_TABLE ('client_sampleID')
=
table 2 = RESULT_TABLE ('sampleID')
This is the proposed trigger
CREATE DEFINER = `user`#`%` TRIGGER `database`.`RESULT_TABLE_BEFORE_INSERT`
AFTER INSERT ON `RESULT_TABLE` FOR EACH ROW
BEGIN
UPDATE SAMPLE_TABLE
SET status = 'complete'
WHERE SAMPLE_TABLE.client_sampleID = RESULT_TABLE.sampleID;
END
My questions:
is this above trigger OK?
there are 100+ 'client_sampleID' (all same, entered as a batch) per 'sampleID'. Is there a more efficient way of setting the 'status' so that it happens only after encountering the first instance?
You are very close. You just need to use new in the trigger:
CREATE DEFINER = `user`#`%` TRIGGER `database`.`RESULT_TABLE_BEFORE_INSERT`
AFTER INSERT ON `RESULT_TABLE` FOR EACH ROW
BEGIN
UPDATE SAMPLE_TABLE st
SET status = 'complete'
WHERE st.client_sampleID = new.sampleID;
END
I have a Trigger on UPDATE.
What is the correct procedure for referencing attribute from the table that is not updated by the UPDATE SQL command? Is the attribute still in the UPDATE variable? I would like to get the value of that attribute for the updated row.
You can access a values of a column before update and after update in MySQL by using keywords OLD and NEW.
For example if you want to determine whether a value of a column actually has been changed during updated you can do
IF NOT OLD.column_name <=> NEW.column_name THEN
-- do something here
END IF;
Note: <=> is NULL-safe comparison operator in MySQL
BTW: There is no UPDATED virtual table in MySQL. It's from SQL Server.
Here is a SQLFiddle demo. Note that even though update affected all records in the table, only one message has been logged in log table. It's because value for a row with id 2 in the end stayed the same.
UPDATE: to keep your finished flag in sync you need triggers for all events (insert, update, delete).
DELIMITER //
CREATE TRIGGER tg_ai_event
AFTER INSERT ON event
FOR EACH ROW
BEGIN
UPDATE activity a
SET status = (EXISTS(SELECT *
FROM event
WHERE activity = a.activity_id
AND done = 0))
WHERE activity_id = NEW.activity;
END//
CREATE TRIGGER tg_ad_event
AFTER DELETE ON event
FOR EACH ROW
BEGIN
UPDATE activity a
SET status = (EXISTS(SELECT *
FROM event
WHERE activity = a.activity_id
AND done = 0))
WHERE activity_id = OLD.activity;
END//
CREATE TRIGGER tg_au_event
AFTER UPDATE ON event
FOR EACH ROW
BEGIN
IF NOT OLD.activity <=> NEW.activity THEN
-- if activity id was changed for an event then clculate finished flag
-- for both old and new activity id
UPDATE activity a
SET status = (EXISTS(SELECT *
FROM event
WHERE activity = a.activity_id
AND done = 0))
WHERE activity_id IN(OLD.activity, NEW.activity);
ELSE
-- otherwise calculate finished flag only if done flag is changed
IF NOT OLD.done <=> NEW.done THEN
UPDATE activity a
SET status = (EXISTS(SELECT *
FROM event
WHERE activity = a.activity_id
AND done = 0))
WHERE activity_id = NEW.activity;
END IF;
END IF;
END//
DELIMITER ;
Here is SQLFiddle demo
I have two tables: table1 and table2, which triggers on inserts and on updates in the same function.
As you insert a value in table1 or table2 a value is inserted in table3, with the value table1.lastname || table1.firstname assigned to column3. The id obtained for the insert in table3 must be inserted into table1.id_table3.
CREATE OR REPLACE FUNCTION myschema.myfunction() RETURNS trigger AS
$BODY$
DECLARE
new_id_table_4 integer;
BEGIN
IF TG_OP = 'INSERT' THEN
IF TG_TABLE_NAME = 'table1' THEN
new_id_table_4 := 1;
ELSIF TG_TABLE_NAME = 'table2' THEN
new_id_table_4 := 2;
END IF;
INSERT INTO myschema.table3
(id, id_table4, name)
VALUES (DEFAULT, new_id_table_4, NEW.columnA||', '||NEW.columnB, TRUE, TRUE)
RETURNING id
INTO NEW.id_table3;
ELSIF TG_OP = 'UPDATE' THEN
IF OLD.columnA <> NEW.columnA OR OLD.columnB <> NEW.columnB THEN
UPDATE myschema.table3 SET
name = NEW.columnA||', '||NEW.columnB
WHERE id = NEW.id_cuenta;
END IF;
END IF;
RETURN NEW;
END
$BODY$
LANGUAGE plpgsql VOLATILE COST 100;
ALTER FUNCTION myschema.myfunction() OWNER TO myuser;
CREATE TRIGGER add_table3record_table1
AFTER INSERT OR UPDATE
ON myschema.table1
FOR EACH ROW
EXECUTE PROCEDURE myschema.myfunction();
CREATE TRIGGER add_table3record_table2
AFTER INSERT OR UPDATE
ON myschema.table2
FOR EACH ROW
EXECUTE PROCEDURE myschema.myfunction();
The problem is that when I insert a new record into table1 or table2,
...RETURNING id INTO NEW.id_table3;
It does not seem to have any effect.
This is my first function/trigger ever, and I cannot find the error.
Thank you!
I'm pretty sure you can't update a row AFTER it has already been inserted just by setting NEW.foo = bar.
Either:
Perform an update on the table1 setting the new id_table3 value (which is going to recursively call you ON UPDATE trigger, so be careful), or
Use a BEFORE trigger instead of an AFTER.
Depending on how your foreign keys are set up between table1 and table3, the latter may or may not be an option.