I have a MySQL table , look like this
t id lang title
1 7 en_UK my_title
1 7 kh_KH
I want write a trigger that update title to my_title with the same id is 7
Result
t id lang title
1 7 en_UK my_title
1 7 kh_KH my_title
From my understanding.
DELIMITER $$
CREATE TRIGGER upd_title BEFORE UPDATE ON `term`
FOR EACH ROW BEGIN
IF (NEW.title IS NULL OR NEW.title= '') THEN
SET NEW.title= ??? ;
END IF;
END$$
DELIMITER ;
[UPDATE1]->not works (trigger not being created)
DELIMITER $$
DROP TRIGGER IF EXISTS `update_category_after_insert`
CREATE TRIGGER `update_category` AFTER INSERT ON `categories`
FOR EACH ROW BEGIN
DECLARE loc_title text;
IF (NEW.libelle_categorie IS NULL OR NEW.libelle_categorie= '') THEN
select libelle_categorie into loc_title from categories where NEW.num_noeud= num_noeud and langue = 'en_UK';
SET NEW.libelle_categorie = loc_title;
END IF;
END
DELIMITER ;
[UPDATE2]
DELIMITER $$
CREATE TRIGGER ``update_category_after_insert`` BEFORE INSERT ON `categories`
FOR EACH ROW BEGIN
DECLARE loc_title text;
IF (NEW.libelle_categorie IS NULL OR NEW.libelle_categorie= '') THEN
select libelle_categorie into loc_title from categories where NEW.num_noeud= num_noeud and langue = 'en_UK';
SET NEW.libelle_categorie = loc_title;
END IF;
END
DELIMITER ;
Finally , I found the good solution for my case
UPDATE categories c INNER JOIN categories c2 ON (
c.num_noeud = c2.num_noeud
) SET c.libelle_categorie = c2.`libelle_categorie`
Can you clarify?
Are you trying to pull the value from the title column in the 'en_UK' row that exists when you insert an new row with the same id that HAS the title column not entered?
okay
CREATE TRIGGER upd_title BEFORE UPDATE ON `term`
FOR EACH ROW BEGIN
DECLARE loc_title VARCHAR(20);
IF (NEW.title IS NULL OR NEW.title= '') THEN
select title into loc_title from term where NEW.id = id and lang = 'en_UK';
SET NEW.title= loc_title;
END IF;
END
This should do the trick.
This was my trigger def:
CREATE DEFINER = CURRENT_USER TRIGGER `therinks`.`glreturndata_BEFORE_UPDATE` BEFORE UPDATE ON `glreturndata` FOR EACH ROW
BEGIN
DECLARE myVal VARCHAR(20);
if NEW.DESCRIPTION IS NULL or new.description = '' THEN
SELECT min(description) into myVal from glreturndata where category = NEW.category and new.idglreturndata <> idglreturndata;
Set NEW.DESCRIPTION = myval;
end if;
END
It seems that you can't do all this in a trigger. According to the documentation:
Within a stored function or trigger, it is not permitted to modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger.
According to this answer, it seems that you should:
create a stored procedure, that inserts into/Updates the target table, then updates the other row(s), all in a transaction.
With a stored proc you'll manually commit the changes (insert and update). I haven't done this in MySQL, but this post looks like a good example.
Related
I have a MariaDB database and I have table userInfo which has a column of ipAddress and country. I want to have another column named country and automatically get the country from the ipAddress and insert it in the country column. I already imported GeoIPLite2 and already have a SQL Query but I dont know how to use make mariadb do it instead of doing it on my code.
SELECT a.country_name
FROM geoipcountries a, geoipblocks b
WHERE INET_ATON('1.2.3.4') BETWEEN network_start_integer AND network_last_integer
AND b.geoname_id = a.geoname_id
This query give me the country name.
I want the MySQL to set the value of country column in userInfo table from the output of the query above.
I already wrote this function as well:
DELIMITER $$
CREATE FUNCTION getIpCountry(ip varchar(15)) RETURNS varchar(64)
BEGIN
declare result varchar(64);
select SQL_CACHE a.country_name into result FROM geoipcountries a, geoipblocks b WHERE INET_ATON(ip) BETWEEN network_start_integer AND network_last_integer AND b.geoname_id = a.geoname_id;
if (result is null) or (result = '') then
set result := 'unknown';
end if;
return result;
END$$
DELIMITER ;
IF you want to change all county names in one goal
Do a
UPDATE userInfo SET `country`= getIpCountry(`ipAddress `);
But today we use join and not comma separated tables
DELIMITER $$
CREATE FUNCTION getIpCountry(ip varchar(15)) RETURNS varchar(64)
BEGIN
declare result varchar(64);
SELECT
a.country_name
INTO result
FROM
geoipcountries a
INNER JOIN
geoipblocks b ON b.geoname_id = a.geoname_id
WHERE
INET_ATON(ip) BETWEEN network_start_integer AND network_last_integer;
if (result is null) or (result = '') then
set result := 'unknown';
end if;
return result;
END$$
DELIMITER ;
To d that automatically you need a BEFORE INSERT TRIGGER
DELIMITER $$
CREATE TRIGGER before_userInfo_insert
BEFORE INSERT
ON userInfo FOR EACH ROW
BEGIN
SET NEW.`country`= getIpCountry(NEW.`ipAddress `);
END $$
DELIMITER ;
and a BEFORE UPDATE TRIGGER
CREATE TRIGGER before_userInfo_update
BEFORE UPDATE
ON userInfo FOR EACH ROW
BEGIN
SET NEW.`country`= getIpCountry(NEW.`ipAddress `);
END $$
DELIMITER ;
Considering you table is userInfo and you want your country column to auto populate based on ipAddress. Use CREATE TRIGGER
DELIMITER $$
CREATE TRIGGER `userinfo_before_insert` BEFORE INSERT ON `userInfo` FOR EACH ROW BEGIN
SET NEW.country = getIpCountry(NEW.ipAddress);
END $$
Note: If ipAddress can be null, so make sure you handle that in your function getIpCountry function.
Same you can on on update event too.
DELIMITER $$
CREATE TRIGGER `userinfo_before_update` BEFORE UPDATE ON `userInfo` FOR EACH ROW BEGIN
SET NEW.country = getIpCountry(NEW.ipAddress);
END $$
Now just skip country column from both INSERT and UPDATE query and make sure to include ipAddress. It would be like as follow
INSERT INTO userInfo(user_id, ipAddress) VALUES (1, '172.16.6.20');
UPDATE userInfo SET ipAddress = '172.16.6.20' WHERE user_id = 1;
This
CREATE TRIGGER pubdate BEFORE UPDATE ON `table1` FOR EACH ROW SET NEW.date=NOW()
on any column update in table would SET date=NOW().
How to add exception when updating columns id and name?
Update: basically run TRIGGER pubdate on update any table column except id and/or name.
Mysql doesn't support column-based trigger actions, so your intention can't be coded at the action level of the trigger.
You can simulate the action in the logic of the rigger though by checking if any if the other columns have changed.
Assuming there are 3 other columns col1, col2, col3:
DELIMITER $$
CREATE TRIGGER pubdate BEFORE UPDATE ON `table`
FOR EACH ROW BEGIN
IF NOT (NEW.col1 <=> OLD.col1
AND NEW.col2 <=> OLD.col2 -- compare more other column as required
AND NEW.col3 <=> OLD.col3) THEN
SET NEW.date = NOW();
END IF;
END$$
DELIMITER ;
FYI the <=> operator is mysql's null-safe equals, which considers null <=> null to be true.
If trigger is to be triggered when the id/name have not been touched:
DELIMITER $$
CREATE TRIGGER pubdate BEFORE UPDATE ON `table1`
FOR EACH ROW BEGIN
IF (NEW.id = OLD.id and NEW.name = OLD.name) THEN -- Condition for updating
SET NEW.date = NOW();
END IF;
END$$
DELIMITER ;
[Updated]
If the trigger is to be triggered when columns other than id/name have been touched (should be triggered when any_other_column and id/name are touched) as well:
DELIMITER $$
CREATE TRIGGER pubdate BEFORE UPDATE ON `table1`
FOR EACH ROW BEGIN
IF (NEW.email <> OLD.email or NEW.other_column1 <> OLD.other_column1 ... ) THEN
-- Do this for all other columns in the table (except for id and name)
SET NEW.date = NOW();
END IF;
END$$
DELIMITER ;
I have 3 tables named opproduct, opcategory and opproduct_to_category.The opproduct table has an after insert and an after delete trigger. These triggers modify the category table content column, but it gets the category_id trough opproduct_to_category table. The statments of triggers roughly the same. The after update is working well, but after insert doesn't modify the category table.
Thanks for your answers!
DROP TRIGGER IF EXISTS opproduct_AINS;
DELIMITER $$
CREATE TRIGGER `opproduct_AINS` AFTER INSERT ON `opproduct`
FOR EACH ROW BEGIN
DECLARE _category_id INT;
IF new.`status`='1' THEN
SELECT category_id INTO _category_id
FROM opproduct_to_category
WHERE product_id = NEW.product_id;
UPDATE opcategory
SET content = content+1
WHERE category_id=_category_id;
END IF;
END$$
DELIMITER ;
DROP TRIGGER IF EXISTS opproduct_AUPD;
DELIMITER $$
CREATE TRIGGER `opproduct_AUPD` AFTER UPDATE ON `opproduct`
FOR EACH ROW BEGIN
DECLARE _category_id INT;
IF NEW.`status`<> OLD.`status` AND NEW.`status`=1 THEN
SELECT category_id INTO _category_id
FROM opproduct_to_category
WHERE product_id = NEW.product_id;
UPDATE opcategory SET content = content+1
WHERE category_id=_category_id;
ELSEIF NEW.`status`<> OLD.`status` AND NEW.`status`=0 THEN
SELECT category_id INTO _category_id
FROM opproduct_to_category
WHERE product_id = NEW.product_id;
UPDATE opcategory SET content = content-1
WHERE category_id=_category_id;
END IF;
END$$
DELIMITER ;
I am trying to create a mysql trigger. The error code 1064 is very generic. The trigger is to see if a record exists for a particular key; and if it does update a particular column in the newly inserted row with that value. I am using a select query on the same table as the trigger is on. Does that cause a problem? Here is the code:
DELIMITER $$
CREATE TRIGGER classid_insert
AFTER INSERT ON courses_semester
FOR EACH ROW
BEGIN
SET #class_id = (SELECT class_id FROM courses_semester WHERE
course_id = NEW.`course_id`
AND `dept_id` = NEW.`dept_id`
AND `univ_id` = NEW.`univ_id`
AND `section_id` = NEW.`section_id`
AND `semester` = NEW.`semester`
AND `year` = NEW.`year`);
IF(#class_id = NULL)
THEN
NEW.class_id = UUID()
ELSE
NEW.class_id = #class_id
END IF;
END
DELIMITER ;
your entire trigger code should look like below. remove the spaces after DELIMITER $$ and before DELIMITER ;. Also, the last END need to changed to END $$. Also, it has to be an BEFORE trigger and not an AFTER trigger.
Moreover, NEW.class_id = UUID() is not correct.It's missing SET as
SET NEW.class_id = UUID();
CORRECTED TRIGGER CODE:
DELIMITER $$
CREATE TRIGGER classid_insert
BEFORE INSERT ON courses_semester
FOR EACH ROW
BEGIN
SET #class_id = (SELECT class_id FROM courses_semester WHERE
course_id = NEW.`course_id`
AND `dept_id` = NEW.`dept_id`
AND `univ_id` = NEW.`univ_id`
AND `section_id` = NEW.`section_id`
AND `semester` = NEW.`semester`
AND `year` = NEW.`year`);
IF(#class_id = NULL)
THEN
SET NEW.class_id = UUID();
ELSE
SET NEW.class_id = #class_id;
END IF;
END $$
DELIMITER ;
I have a table that I want : when the table has been updated, 2 fields of that (title and description) change and take value from another table
This is my trigger:
drop trigger trigger_trade_request ;
CREATE TRIGGER trigger_trade_request AFTER UPDATE ON `trade_request`
FOR EACH ROW
BEGIN
IF NEW.title = null THEN
UPDATE `trade_request_type`,`trade_request`
SET NEW.title = `trade_request_type`.title ,
NEW.description = `trade_request_type`.description
WHERE `trade_request_type`.id = NEW.trade_request_typeId;
END IF;
END;
My tables:
trade_request_type
trade_request
error:
ERROR 1442 : Can't update table 'trade_request' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
It does not work! What is the prob?
Use is null to check for null values.
To change the value of the updated row use BEFORE trigger and SET on the NEW row.
Try this:
CREATE TRIGGER trigger_update_request BEFORE UPDATE ON `trade_request`
FOR EACH ROW
BEGIN
IF NEW.title IS NULL THEN
SET NEW.title = (SELECT title FROM trade_request_type
WHERE trade_request_type.id = NEW.trade_request_typeId);
SET NEW.description = (SELECT description FROM trade_request_type
WHERE trade_request_type.id = NEW.trade_request_typeId);
END IF;
END;
Probably you can use the SELECT...INTO syntax instead of SET, like so:
CREATE TRIGGER trigger_update_request BEFORE UPDATE ON `trade_request`
FOR EACH ROW
BEGIN
IF NEW.title IS NULL THEN
SELECT title, description
FROM trade_request_type
WHERE trade_request_type.id = NEW.trade_request_typeId
INTO NEW.tile, NEW.description;
END IF;
END;
This is because you are trying to update the other table too.
Try that:
UPDATE `trade_request`
SET NEW.title = `trade_request_type`.title ,
NEW.description = `trade_request_type`.description
FROM `trade_request_type`
WHERE `trade_request_type`.id = NEW.trade_request_typeId;
AND `trade_request_type`.id = `trade_request`.id
Three problems:
To test for null, use is null (not = null which is never true)
To set new values in your incoming row, use NEW.column = some_value
You can't update a table twice in one trigger
Try this:
drop trigger trigger_trade_request ;
CREATE TRIGGER trigger_trade_request BEFORE UPDATE ON `trade_request`
FOR EACH ROW
BEGIN
IF NEW.title is null THEN
SET NEW.title = (select title from trade_request_type WHERE trade_request_type.id = NEW.trade_request_typeId);
SET NEW.description = (select description from trade_request_type WHERE trade_request_type.id = NEW.trade_request_typeId);
END IF;
END;