Im having problems with this MYSQL trigger cant seem to figure it out what the problem is. i have tables like the following.
create table assets(
id int,
model_id int,
asset_type varchar(6)
);
create table models(
id int,
category_id int,
name varchar(20)
);
create table categories(
id int,
cat_prefix varchar(4)
);
With that i want to have the cat_prefix value to be inserted in the asset_type column for every insert on the assets table based on model_id. Of course this are simplified versions of the tables.
So i wrote an insert trigger below.
DELIMITER //
CREATE TRIGGER asset_prefix_after_insert AFTER INSERT ON assets
FOR EACH ROW
BEGIN
DECLARE model_id INT DEFAULT NULL ;
DECLARE category_id INT DEFAULT NULL ;
DECLARE category_prefix VARCHAR(6);
DECLARE msg varchar(128);
SELECT NEW.model_id INTO model_id;
IF (model_id IS NOT NULL) THEN
SELECT category_id from models
WHERE id = model_id
INTO category_id;
END IF;
IF (category_id IS NOT NULL) THEN
SELECT cat_prefix from categories
WHERE id = category_id
INTO category_prefix;
END IF;
IF (category_prefix IS NOT NULL) THEN
INSERT INTO assets
(asset_type)
VALUES (category_prefix);
END IF;
END //
DELIMITER ;
But it does nothing on insert. What im i missing here?. Please help. Thanks.
Best Answer
Mostly just a few little mistakes, the biggest of which is the ambiguous declaration of
category_id
.This statement is selecting value of the
DECLARE
'dcategory_id
( which is theDEFAULT
, null ), into theDECLARE
'dcategory_id
. This renders the following branches unreachable, as they will always evaluate as false. To eliminate this ambiguity, you can alias your table.The lesson here is to always alias your tables. As per natural law, for every opinion there is an equal and opposite opinion, but in this case, I'm right. Alias your tables, all the time, every time. It drastically improves readability and serves to avoid little bugs like this one.
The next issue with the trigger is a discrepancy between what you have said ( insert a value into the
asset_type
column for each row ) and what you've coded ( insert a row into theassets
table for each row ).This statement says to insert the [ (null), (null), category_prefix ] tuple into the asset table. In addition to likely not being the actual intent, as your trigger is an after-insert trigger, if the trigger were to actually perform this operation it would infinitely loop. What you need to do is to set the value of the
NEW
column:However, MySQL will also complain about this because you can't update a NEW column in an after-insert trigger, as the write has already completed: It's already done. To make this work, it's necessary to change the trigger from an after-insert to a before-insert.
With those changes, you may end up with something that looks a little like the following: