creating a trigger - declare variable - Cant get my trigger to work - mysql

This trigger is designed to update 'field_csvfilepath_value' to match 'filepath' in the files table (some table details below). But I cant get it to work, please help.
delimiter $$
CREATE TRIGGER csv_filpath
AFTER INSERT ON content_type_importcsv for each row
begin
declare p varchar(80)
set p := (SELECT filepath FROM content_type_importcsv join files where NEW.content_type_importcsv.field_csv1_fid = files.fid)
set NEW.field_csvfilepath_value = p
end$$
delimiter ;
This trigger is generating the following error:
Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'set p := (SELECT filepath FROM content_type_importcsv join files where NEW.conte' at line 5
I'm using mysql workbench 5.2
delimiter $$
delimiter $$
CREATE TABLE `content_type_importcsv` (
`vid` int(10) unsigned NOT NULL DEFAULT '0',
`nid` int(10) unsigned NOT NULL DEFAULT '0',
`field_csv1_fid` int(11) DEFAULT NULL,
`field_csv1_list` tinyint(4) DEFAULT NULL,
`field_csv1_data` text,
`field_csvfilepath_value` longtext,
PRIMARY KEY (`vid`),
KEY `nid` (`nid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8$$
CREATE TABLE `files` (
`fid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`uid` int(10) unsigned NOT NULL DEFAULT '0',
`filename` varchar(255) NOT NULL DEFAULT '',
`filepath` varchar(255) NOT NULL DEFAULT '',
`filemime` varchar(255) NOT NULL DEFAULT '',
`filesize` int(10) unsigned NOT NULL DEFAULT '0',
`status` int(11) NOT NULL DEFAULT '0',
`timestamp` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`fid`),
KEY `uid` (`uid`),
KEY `status` (`status`),
KEY `timestamp` (`timestamp`)
) ENGINE=MyISAM AUTO_INCREMENT=55 DEFAULT CHARSET=utf8$$

Apart from multiple syntax errors in your code you can't change column values of a row being inserted in AFTER trigger. You should use BEFORE event instead.
That being said your trigger can be boiled down to one-statement and therefore doesn't need BEGIN ... END block and change of a delimiter.
CREATE TRIGGER csv_fillpath
BEFORE INSERT ON content_type_importcsv
FOR EACH ROW
SET NEW.field_csvfilepath_value =
(
SELECT filepath
FROM files
WHERE fid = NEW.field_csv1_fid
LIMIT 1
);
Here is SQLFiddle demo

There are some syntax errors:
The one you listed is caused by the : in set p :=, you should remove it
Each line between begin and end$$ should end with ;
You can't update a NEW row in an after trigger, so it should be a before trigger

Related

my trigger error in mysql, hen help to fix

I can't understand why my trigger doesn't work.
first table:
CREATE TABLE `Payment` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`idPaymentMethod` int(20) DEFAULT NULL,
`createAt` timestamp NOT NULL DEFAULT current_timestamp(),
`updateAt` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE current_timestamp(),
`actived` tinyint(1) NOT NULL DEFAULT 1,
`numberInvoices` int(11) DEFAULT NULL,
`preferentialPaymentDay` int(11) DEFAULT NULL,
`invoicesFrequency` bigint(20) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
second table:
CREATE TABLE `PaymentHistory` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`idPaymentMethod` int(20) DEFAULT NULL,
`idPayment` int(20) DEFAULT NULL,
`createAt` timestamp NOT NULL DEFAULT current_timestamp(),
`updateAt` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE current_timestamp(),
`actived` tinyint(1) NOT NULL DEFAULT 1,
`numberInvoices` int(11) DEFAULT NULL,
`preferentialPaymentDay` int(11) DEFAULT NULL,
`invoicesFrequency` bigint(20) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
my trigger:
DELIMITER $$
CREATE
TRIGGER `update_history` AFTER
UPDATE
ON
`Payment`
FOR EACH ROW BEGIN
UPDATE
`PaymentHistory`
SET
id = OLD.id,
idPaymentMethod = old.idPaymentMethod,
createAt = old.createAt,
updateAt = old.updateAt,
actived = old.actived,
numberInvoices = old.numberInvoices
END$$
I get a lot of errors when I try to fix something.
Errors I get:
SQL Error [1064] [42000]: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'END$$' at line 1
SQL Error [1054] [42S22]: Unknown column 'OLD.id' in 'field list'
I am really lost.
I need all the updated data in the "Payment" table to be inserted or updated into the "PaymentHistory" table
Plase, i need a help.
You need to finish each command with a semicolon
DELIMITER $$
CREATE
TRIGGER `update_history` AFTER
UPDATE
ON
`Payment`
FOR EACH ROW BEGIN
UPDATE
`PaymentHistory`
SET
id = OLD.id,
idPaymentMethod = old.idPaymentMethod,
createAt = old.createAt,
updateAt = old.updateAt,
actived = old.actived,
numberInvoices = old.numberInvoices;
END$$
DELIMITER ;
See example
first, thanks to #nbk
i solved with yours help
i change de "after" to "before" and add the ";"
see;
TRIGGER `update_history` BEFORE
UPDATE
ON
`Payment`
FOR EACH ROW BEGIN
UPDATE
`PaymentHistory`
SET
idPayment = old.id
, idPaymentMethod = old.idPaymentMethod
, createAt = old.createAt
, updateAt = old.updateAt
, actived = old.actived
, numberInvoices = old.numberInvoices;
END

Using Auto-Increment value in MYSQL Before Insert Trigger?

The users table:
CREATE TABLE `users` (
`id` int(8) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(45) DEFAULT NULL,
`username` varchar(16) DEFAULT NULL,
`salt` varchar(16) DEFAULT NULL,
`password` varchar(128) DEFAULT NULL,
`lastlogin` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`joined` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`loggedin` tinyint(1) unsigned NOT NULL DEFAULT '0',
`sessionkey` varchar(60) DEFAULT NULL,
`verifycode` varchar(16) DEFAULT NULL,
`verified` tinyint(1) unsigned NOT NULL DEFAULT '0',
`banned` tinyint(1) unsigned NOT NULL DEFAULT '0',
`locked` tinyint(1) unsigned NOT NULL DEFAULT '0',
`ip_address` varchar(45) DEFAULT NULL,
`failedattempts` tinyint(1) unsigned NOT NULL DEFAULT '0',
`unlocktime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;
The user_records table:
CREATE TABLE `user_records` (
`id` int(8) unsigned NOT NULL AUTO_INCREMENT,
`userid` int(8) unsigned DEFAULT NULL,
`action` varchar(100) DEFAULT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
The before insert trigger on the users table:
USE `gknet`;
DELIMITER $$
CREATE DEFINER=`root`#`localhost` TRIGGER `before_create_user` BEFORE INSERT ON `users` FOR EACH ROW BEGIN
INSERT INTO user_records (action, userid, timestamp)
VALUES ('CREATED', ID, NOW() );
END
Basically, my problem here is that on the trigger when I try to put in the id of the user that's automatically assigned by MySQL (PK, NN, Auto-Increment), it just puts in 0 for userid on the user_records table. How would I do it so it would select the id that the user is being assigned by SQL, and put it in as userid on the records entry (where the ID is right after 'CREATED')?
Also, if you see any other optimizations that could be made on the tables, feel free to let me know :D
OP's comment:
How would I do it before, thou?
You can find current auto_increment value that is to be assigned to a new record.
And use the same in the before trigger as a parent user id for user_records table.
You have to query information_schema.tables table to find the value.
Example:
use `gknet`;
delimiter $$
drop trigger if exists before_create_user; $$
create definer=`root`#`localhost` trigger `before_create_user`
before insert on `users`
for each row begin
declare fk_parent_user_id int default 0;
select auto_increment into fk_parent_user_id
from information_schema.tables
where table_name = 'users'
and table_schema = database();
insert into user_records ( action, userid, timestamp )
values ( 'created', fk_parent_user_id, now() );
end;
$$
delimiter ;
Observations:
As per mysql documentation on last_insert_id(),
"if you insert multiple rows using a single INSERT statement,
LAST_INSERT_ID() returns the value generated for the first inserted
row only."
hence, depending on last_insert_id() and auto_increment field values in batch inserts seems not reliable.
Change the trigger to after insert instead of before insert and use NEW to get the last inserted id
USE `gknet`;
DELIMITER $$
CREATE DEFINER=`root`#`localhost`
TRIGGER `after_create_user` AFTER INSERT ON `users`
FOR EACH ROW
BEGIN
INSERT INTO user_records (action, userid, timestamp)
VALUES ('CREATED', NEW.ID, NOW() );
END; $$
PLEASE USE AFTER INSERT AND UPDATE
Do not make auto_increment any column you want to manipulate explicitly. That can confuse an engine and cause serious problems. If no column you have used for primary key are auto_increment you can do anything you want with them via triggers. Sure generated values will be rejected if they violate the mandatory uniqness of the primary key.
maybe this solution can
BEGIN
DECLARE id int;
SELECT MAX(table_id)
FROM table
INTO id;
IF id IS NULL THEN
SET NEW.column=(CONCAT('KTG',1));
ELSE
SET NEW.column=(CONCAT('KTG',id+1));
END IF;
END

MySql - can BEFORE INSERT TRIGGER insert into 2 columns?

Can this trigger be changed so that the sortorder table gets 2 column values (sortOrderId, sortOrder) inserted?
How is the value of sortOrder found?
If it is known and can be inserted into image table then can it also be inserted into the sortorder table?
-- Trigger DDL Statements
DELIMITER $$
USE `nextcart`$$
CREATE
DEFINER=`root`#`localhost`
TRIGGER `nextcart`.`insert_sortorderid`
BEFORE INSERT ON `nextcart`.`image`
FOR EACH ROW
BEGIN
INSERT INTO sortorder SET sortOrderId = NULL, sortOrder = NEW.sortOrder;
SET NEW.sortOrderId = (SELECT LAST_INSERT_ID());
END;
$$
CREATE TABLE sortorder:
delimiter $$
CREATE TABLE `sortorder` (
`sortOrderId` int(11) NOT NULL AUTO_INCREMENT,
`sortOrder` tinyint(4) NOT NULL,
PRIMARY KEY (`sortOrderId`),
KEY `sort_order` (`sortOrderId`,`sortOrder`),
CONSTRAINT `fk_sortOrderId` FOREIGN KEY (`sortOrderId`) REFERENCES `image` (`imageId`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8$$
CREATE TABLE image:
delimiter $$
CREATE TABLE `image` (
`imageId` int(11) NOT NULL AUTO_INCREMENT,
`imageFileName` varchar(45) DEFAULT NULL,
`imagePath` varchar(255) DEFAULT NULL,
`imageTitle` varchar(100) DEFAULT NULL,
`imageAlt` varchar(100) DEFAULT NULL,
`imageWidth` int(11) DEFAULT NULL,
`imageHeight` int(11) DEFAULT NULL,
`classId` int(11) DEFAULT NULL,
`imageSizeId` tinyint(4) NOT NULL,
`isImageEnabled` bit(1) DEFAULT b'0',
`sortOrderId` int(11) DEFAULT NULL,
PRIMARY KEY (`imageId`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8$$
ERROR MESSAGE:
Error 1054: Unknown column 'sortOrder' in 'NEW' SQL Statement:
CREATE TRIGGER insert_sortorderid BEFORE INSERT ON image FOR EACH
ROW BEGIN INSERT INTO nextcart.sortorder SET sortOrderId = NULL,
sortOrder = NEW.sortOrder; SET NEW.sortOrderId = ( SELECT
LAST_INSERT_ID()); END; Error when running failback script. Details
follow. Error 1050: Table 'image' already exists SQL Statement: CREATE
TABLE image ( imageId int(11) NOT NULL AUTO_INCREMENT,
imageFileName varchar(45) DEFAULT NULL, imagePath varchar(255)
DEFAULT NULL, imageTitle varchar(100) DEFAULT NULL, imageAlt
varchar(100) DEFAULT NULL, imageWidth int(11) DEFAULT NULL,
imageHeight int(11) DEFAULT NULL, classId int(11) DEFAULT NULL,
imageSizeId tinyint(4) NOT NULL, isImageEnabled bit(1) DEFAULT
b'0', sortOrderId int(11) DEFAULT NULL, PRIMARY KEY (imageId)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
There is no column named sortOrder in the image table.
So, the reference to NEW.sortOrder (on the insert statement in the trigger) is invalid.
To answer your first question: No. Since there is no value supplied for that in the INSERT statement (which fires the BEFORE INSERT TRIGGER), you don't really have a source for that value.
The easy option is to provide a default value for it.
If you want to supply a value for the sortOrder column, then one option is to add a sortOrder column to the image table, and then the value can be supplied in the INSERT INTO image statement. Then it would available in the trigger.
(The purpose of the sortorder table is not at all clear.)

Mysql Trigger Loop for query result with many rows

hi i have a database with many tables and foreign keys like this
CREATE TABLE IF NOT EXISTS `articulos` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`nombre` varchar(63) NOT NULL,
`contenido` text NOT NULL,
`normas_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=138 ;
CREATE TABLE IF NOT EXISTS `aspectosambientales` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`nombre` varchar(63) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=28 ;
CREATE TABLE IF NOT EXISTS `aspectosambientales_articulos` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`aspectosambientales_id` int(11) NOT NULL,
`articulos_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_aspaspectosambientales1` (`aspectosambientales_id`),
KEY `fk_aspee` (`articulos_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 UTO_INCREMENT=225 ;
CREATE TABLE IF NOT EXISTS `empresas` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`razonsocial` varchar(127) DEFAULT NULL,
`nit` varchar(63) DEFAULT NULL,
`direccion` varchar(127) DEFAULT NULL,
`telefono` varchar(15) DEFAULT NULL,
`web` varchar(63) DEFAULT NULL,
`auth_user_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
CREATE TABLE IF NOT EXISTS `articulos_empresas` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`empresas_id` int(11) NOT NULL,
`articulo_id` int(11) NOT NULL,
`acciones` text,
`responsable` varchar(255) DEFAULT NULL,
`plazo` date DEFAULT NULL,
`cumplido` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_normas_empresas_empresas1` (`empresas_id`),
KEY `fk_normas_empresas_normas1` (`normas_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
and i need to create a trigger to fill the 'articulos_empresas' after insert in 'empresas' for all rows in 'articulos' that match with 'aspectosambientals' that the new 'empresas' selected.
I get all 'articulos' with this query
SELECT articulos_id FROM aspectosambientales_articulos
WHERE aspectosambientales_id = ID
-- ID is the aspectosambientales_id selected when the 'empresas' row is created
-- maybe something like NEW.aspectosambientales_id
but i dont know how create a loop like ' for loop' in trigger for every result in the query
some like this:
CREATE TRIGGER 'filltableae' AFTER INSERT ON 'empresas'
FOR EACH ROW
BEGIN
DECLARE arrayresult = (SELECT articulos_id FROM aspectosambientales_articulos
WHERE aspectosambientales_id = NEW.aspectosambientales_id)
--- here is when i have to do the loop for all the results
--- for ids in arrayresults
--- insert into articulos_empresas ('',NEW.id, ids, '', '' ,'','')
--- endfor
END
thanks!!!
Based on #Razvan answer i left here the code for the trigger, so maybe can help somebody
DROP TRIGGER IF EXISTS AEINST;
DELIMITER //
CREATE TRIGGER AEINST AFTER INSERT ON procesos_aspectos
FOR EACH ROW
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE ids INT;
DECLARE cur CURSOR FOR SELECT articulos_id FROM aspectosambientales_articulos WHERE aspectosambientales_id = NEW.aspectosambientales_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
ins_loop: LOOP
FETCH cur INTO ids;
IF done THEN
LEAVE ins_loop;
END IF;
INSERT INTO articulos_empresas VALUES (null,ids, NEW.empresas_id,null,null,null,null);
END LOOP;
CLOSE cur;
END; //
DELIMITER ;
thanks again!
As far as I know you can iterate through the result of a SELECT query using cursors.
See here : http://dev.mysql.com/doc/refman/5.0/en/cursors.html

MySQL trigger to set column to max + 1 not working

I'm having difficulty writing a trigger that sets the rank column to the max rank value plus 1 for a group of user ids. Maybe the code would be more helpful than my description:
CREATE TABLE `saved_listing` (
`saved_listing_id` int(10) NOT NULL auto_increment,
`user_id` int(10) NOT NULL default '0',
`listing_id` int(10) NOT NULL default '0',
`listing_ty` varchar(10) NOT NULL default '',
`notes` text NULL,
`rank` int(10) NOT NULL default '0',
`modify_by` int(10) NOT NULL default '1',
`modify_dt` timestamp NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
`create_by` int(10) NOT NULL default '1',
`create_dt` datetime NOT NULL default '0000-00-00 00:00:00',
`active` enum('Yes','No') NOT NULL default 'No',
PRIMARY KEY (`saved_listing_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=0 ;
Here's my trigger code:
CREATE TRIGGER ins_saved_listing BEFORE INSERT ON saved_listing
FOR EACH ROW BEGIN
SET NEW.create_dt = NOW();
SET NEW.rank = (SELECT MAX(rank) + 1 FROM saved_listing WHERE user_id = NEW.user_id);
END
Here's the error message I'm getting:
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 3
Any help would be greatly appreciated. I don't have much experience writing triggers.
MySQL Server version: 5.1.49-3~bpo50+1
That is because mysql sees ; (the delimiter) and breaks the execution of CREATE TRIGGER
Try to change to:
delimiter |
CREATE TRIGGER ins_saved_listing BEFORE INSERT ON saved_listing
FOR EACH ROW BEGIN
SET NEW.create_dt = NOW();
SET NEW.rank = (SELECT MAX(rank) + 1 FROM saved_listing WHERE user_id = NEW.user_id);
END;
|
delimiter ;