Creating a trigger before insert - mysql

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.

Related

Mysql said: #1422 - Explicit or implicit commit is not allowed in stored function or trigger

In the code below I'm trying to create a trigger which inserts 'incidentimg' table id along with an image path if the user of the web application did not upload a image with the form belonging to 'incidentreport' table, however, I'm only getting the error "MySQL said: #1422 - Explicit or implicit commit is not allowed in stored function or trigger"
DROP TRIGGER IF EXISTS `insertImage`;
CREATE TRIGGER `insertImage` AFTER INSERT ON `incidentreport`
FOR EACH ROW
BEGIN
IF(SELECT incidentimg.incidentImgId FROM incidentimg
LEFT JOIN incidentreport ON incidentimg.imgs_incidentReportId = incidentreport.incidentReportId
WHERE incidentimg.incidentImgId IS NULL)
THEN INSERT INTO incidentimg(incidentImgId, imgUrl)values(NEW.incidentReportId, 'images/no-image.png');
END IF;
END
;
Here are the tables being used
Can someone assist me on how to correct this problem
I finally got the code to work. Now the code will check whether 'incidentimg' table has all the 'incidentReportId' that the 'incidentreport' table has, and if it doesn't then the last inserted id from the 'incidentreport' table along with a default image path will be inserted into 'incidentimg' table AFTER INSERT.
CREATE TRIGGER insertImage AFTER INSERT ON incidentreport
FOR EACH ROW
BEGIN
IF(SELECT incidentreport.incidentReportId
FROM incidentreport
LEFT JOIN incidentimg ON incidentreport.incidentReportId = incidentimg.imgs_incidentReportId
WHERE incidentimg.imgs_incidentReportId IS NULL)
THEN INSERT INTO incidentimg(imgs_incidentReportId, imgUrl) VALUES(NEW.incidentReportId, 'images/no-image.png');
END IF;
END
I am not much sure but I am guessing that probably it's because of the IF .. THEN conditional INSERT. Try modifying your INSERT statement with an EXISTS like
DROP TRIGGER IF EXISTS `insertImage`;
CREATE TRIGGER `insertImage` AFTER INSERT ON `incidentreport`
FOR EACH ROW
BEGIN
INSERT INTO incidentimg(incidentImgId, imgUrl)
SELECT NEW.incidentReportId, 'images/no-image.png'
FROM DUAL WHERE EXISTS (
SELECT 1 FROM incidentimg
LEFT JOIN incidentreport
ON incidentimg.imgs_incidentReportId = incidentreport.incidentReportId
WHERE incidentimg.incidentImgId IS NULL
)
END;

After Insert Trigger terminate when error

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

Trigger to return duplicate error in MySQL and to affect the INSERT INTO..... ON DUPLICATE KEY UPDATE

I am having a challenge with MySQL. As you know MySQL does not consider NULL as a duplicate value in the unique indexes.
The problem here is that I have a table but I need to enforces that no similar data to be inserted "including NULL" into the following columns
(call_code_id, result_code_id, action_method, action_id, assign_to, assign_to_type)
You may suggest for me to add a unique index on those columns. The problem that the columns "assign_to" and "assign_id" allows NULL values. So based on MySQL definition of a unique columns the following 2 set of data are not Unique and will be allowed to be inserted
(call_code_id, result_code_id, action_method, action_id, assign_to, assign_to_type)
(1,1,'FINISH',NULL,5,2)
(1,1,'FINISH',NULL,5,2)
so even if I add a unique column, MySQL will allow those 2 rows to be inserted. But I need to prevent that for happening as my application consider those 2 rows duplicates.
I must say here that I update this table using stored procedure and I update the table using INSERT INTO ...... ON DUPLICATE KEY UPDATE statement.
My initial solution was to add a 2 triggers on that table. First trigger for insert and the other for update. Both trigger will return error code 1062 if a similar data was found before insert or update.
That did worked somewhat! But the new challenge is that the error code 1062 that is return by the trigger is not being utilized by the INSERT INTO ...... ON DUPLICATE KEY UPDATE statement. However, it is returning the 1062 error on the screen so it is finding the duplicates as it should. So when I execute the INSERT INTO ...... ON DUPLICATE KEY UPDATE statement I get the error 1062 returned on the screen, instead it should perform an update since I am asking it to update when duplicate records are found.
Here are my triggers syntax
DROP TRIGGER IF EXISTS `return_1062_on_duplicate_on_insert`;
DELIMITER //
CREATE TRIGGER `return_1062_on_duplicate_on_insert` BEFORE INSERT ON `inventory_engine_test`
FOR EACH ROW BEGIN
IF EXISTS(SELECT 1 FROM inventory_engine_test
WHERE call_code_id = NEW.call_code_id
AND result_code_id = NEW.result_code_id
AND action_method = NEW.action_method
AND IFNULL(action_id, 0) = IFNULL(NEW.action_id, 0)
AND IFNULL(assign_to, 0) = IFNULL(NEW.assign_to, 0)
AND assign_to_type = NEW.assign_to_type
AND NEW.engine_id IS NOT NULL) THEN
SIGNAL SQLSTATE '23000'
SET MYSQL_ERRNO = 1062,
TABLE_NAME = 'inventory_engine_test',
MESSAGE_TEXT = 'Duplicate key found - return_1062_on_duplicate_on_insert trigger';
END IF;
END
//
DELIMITER ;
DROP TRIGGER IF EXISTS `return_1062_on_duplicate_on_update`;
DELIMITER //
CREATE TRIGGER `return_1062_on_duplicate_on_update` BEFORE UPDATE ON `inventory_engine_test`
FOR EACH ROW BEGIN
IF EXISTS(SELECT 1 FROM inventory_engine_test
WHERE call_code_id = NEW.call_code_id
AND result_code_id = NEW.result_code_id
AND action_method = NEW.action_method
AND IFNULL(action_id, 0) = IFNULL(NEW.action_id, 0)
AND IFNULL(assign_to, 0) = IFNULL(NEW.assign_to, 0)
AND assign_to_type = NEW.assign_to_type
AND NEW.engine_id IS NOT NULL) THEN
SIGNAL SQLSTATE '23000'
SET MYSQL_ERRNO = 1062,
TABLE_NAME = 'inventory_engine_test',
MESSAGE_TEXT = 'Duplicate key found - return_1062_on_duplicate_on_update trigger';
END IF;
END
//
DELIMITER ;
How can I get INSERT INTO ..... ON DUPLICATE KEY UPDATE to consider the error return by the trigger?
Thanks

PostgreSQL trigger updating secondary related table

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.

Mysql trigger with two tables and if statement

I cannot find any solution for this 'problem'.
My database needs to update a field in one table when another table is updated.
(only when the new value is 5 or 7 and the new prop.key is "status_id")
But the updated table doesn't include the values that I need. It only contains an ID to another table.
I am not sure about the syntax for this statement. This one won't work. Can anybode help me?
This is what I tried:
delimiter $$
CREATE TRIGGER autoClosedOn AFTER INSERT ON journal_details
FOR EACH ROW BEGIN
IF
NEW.prop_key = "status_id"
AND NEW.value = "5"
OR NEW.value = "7"
THEN
UPDATE
issues i
JOIN journals j
ON j.journalized_id = i.id
SET
i.closed_on = j.created_on;
WHERE j.id = NEW.jounal_id;
END IF;
END$$
delimiter ;
You have a superfluous semicolon before the WHERE clause of your update statement.