Update value each time new rows is created - mysql

I have two tables: config(last_inserted_id) and element(id) is there any chance to get the last inserted id any time when new rows are created in element table and execute a update in column last_inserted_id at config table?
I have wrote this:
CREATE TRIGGER UPDATE_CONFIG_VALUES AFTER INSERT ON element
BEGIN
UPDATE config SET last_inserted_id = last_insert_id();
END;
END;
Is that right? What happen if I delete a row in element table? Should the value get updated in config table or not" How I avoid this?
config table
CREATE TABLE IF NOT EXISTS `cmplatform`.`isrl_config` (
`id` INT NOT NULL AUTO_INCREMENT,
`logo_address` VARCHAR(250) NOT NULL,
`name` VARCHAR(250) NOT NULL,
`rif` VARCHAR(20) NOT NULL,
`address` TEXT NOT NULL,
`phone` VARCHAR(14) NOT NULL,
`last_retention_number` INT NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB

TEST this ( Not tested)
CREATE TRIGGER element_inserted_tg AFTER INSERT ON element
FOR EACH ROW
BEGIN
DECLARE count INT;
SELECT COUNT(1) INTO count FROM config;
IF count == 1
UPDATE config SET last_inserted_id = NEW.id;
ELSE
INSERT INTO config VALUES (NEW.id);
END IF;
END;
CREATE TRIGGER element_deleted_tg AFTER DELETE ON element
FOR EACH ROW
BEGIN
UPDATE config SET last_inserted_id = (SELECT MAX(id) FROM element);
END;

Trigger is traditional way to do this requirement but not unique way. Another way is process it in your data access code. Let say that you have a DAO method to create new Element, you can get the id of element created and update it into last_inserted_id. If you do this way, you have to makesure there is ONLY ONE THREAD calling insert element method at a time.

Related

On Insert- Create new entry? Trigger

I currently have two tables for which I have listed the codes below:
CREATE TABLE `class` (
`id` int(11) NOT NULL,
`class_no` int(11) NOT NULL,
`class_title` varchar(11) NOT NULL,
`no_of_students` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `enrolment` (
`id` int(11) NOT NULL,
`ssn` varchar(11) NOT NULL,
`class_no` int(11) NOT NULL,
`grade` varchar(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
I currently have the following statement, which when you enter something into 'Enrolment', and the class number you type in already matches a class_no in the table 'Class', then it adds whatever is typed into grade to no_of_students. What I now need it to do is if someone say typed into enrollment (2, 4, 6, 8) and the class_no 6 didn't already exist in the 'Class' table, it would add into 'Class' with the class_no as 6 and the no_of_students as 8.
DELIMITER $
CREATE TRIGGER `after_insert_add_one`
AFTER INSERT ON `enrolment`
FOR EACH ROW UPDATE class
SET class.no_of_students = class.no_of_students + NEW.grade
WHERE class_no = NEW.class_no
$
DELIMITER ;
(When you add an enrolment row do you really want to increment class.no_of_students by the value of grade? Seems like you might want to increment it by one. I wrote my answer assuming that.)
(I suspect you didn't show, in your question, the indexes definitions for your tables. I suspect you didn't show how your id columns get set. Presumably they are set with autoincrement. If that's not true my answer is probably worthless.)
MySQL offers an INSERT ... ON DUPLICATE KEY UPDATE statement. You can change your trigger to use it, something like this (not debugged).
DELIMITER $
CREATE TRIGGER `after_insert_add_one`
AFTER INSERT ON `enrolment`
FOR EACH ROW
INSERT INTO class
(class_no, no_of_students, grade)
VALUES (NEW.class_no, 1, NEW.grade)
ON DUPLICATE KEY
UPDATE SET class.no_of_students = class.no_of_students + 1$
DELIMITER ;
For this to work correctly you need a unique index on class.class_no. You can create it as follows:
CREATE UNIQUE INDEX class_no ON class (class_no);
By the way, you need some sort of index on class.class_no. Without it neither your original trigger nor the new one will perform very well. And, your "business rules" seem to require each value of class_no to have just one row in the class table. So you may as well use a unique index.
Pro tip: Giving your columns accurate and descriptive names is almost always worth a lot of trouble early in your project. If, for example, the column grade actually is a count of new students, you'll create years of confusion. The more successful your project is, the more confusion you'll create.
This can be done in app logic or with a trigger, the later below:
CREATE TRIGGER after_insert_add_one AFTER INSERT ON enrolment FOR EACH ROW
BEGIN
DECLARE counter int DEFAULT -1;
SELECT COUNT() INTO counter
FROM class
WHERE class_no = NEW.class_no;
IF counter = 0 THEN
# no classes exist with enrolment ID
INSERT INTO class (class_no) VALUES (NEW.class_no);
ELSE:
# class exists ++
UPDATE class
SET class.no_of_students = class.no_of_students + NEW.grade
WHERE class_no = NEW.class_no;
END IF;
END;

After Insert Trigger on joomla database gives an error1172

I made AFTER INSERT Trigger on joomla database (table _users) which after registration copies user_id and name to another table.
Everything works fine until someone during registration enters a name that already exists Otherwise the column name is not the primary one or unique. I get an error:
Save failed with the following error: Result consisted of more than one row
My trigger looks like this:
BEGIN
DECLARE `new_user` integer;
DECLARE `new_name` VARCHAR(400);
SELECT `id`
INTO `new_user`
FROM `eio3k_users`
WHERE `id` = NEW.id;
SELECT `name`
INTO `new_name`
FROM `eio3k_users`
WHERE `name` = NEW.name;
INSERT INTO `eio3k_point_system`(`user_id`, `name` ) VALUES (NEW.id, NEW.name);
END
What should I do to avoid this error?

MySQL: Integrity error when inserting into database

So, I have this one column in my table that gets filled by a trigger when a new entry is inserted.
CREATE TABLE `users` (
`idusers` int(11) NOT NULL AUTO_INCREMENT,
`uid` char(64) DEFAULT NULL,
`uname` varchar(80) NOT NULL,
`password` char(128) NOT NULL,
`mail` varchar(120) NOT NULL,
PRIMARY KEY (`idusers`),
UNIQUE KEY `uname_UNIQUE` (`uname`),
UNIQUE KEY `mail_UNIQUE` (`mail`),
UNIQUE KEY `uid_UNIQUE` (`uid`)
);
DELIMITER $$
TRIGGER `flask`.`users_BEFORE_INSERT` BEFORE INSERT ON `users` FOR EACH ROW
BEGIN
set new.uid = sha2(new.idusers, 256);
END$$
DELIMITER ;
The problem now is that when I try to add a new row (only have a test one yet because of the error), in the trigger the value of new.idusers is somehow always 0 instead of the current auto_increment value.
What do I need to change in my trigger code so that the value used for generating the uid is the actual id and not always 0?
Since idusers is an AUTO_INCREMENT field, its value is known only after the record is inserted in the table.
Use an AFTER INSERT trigger instead of a BEFORE INSERT trigger, and update the newly inserted record:
DELIMITER $$
CREATE TRIGGER `flask`.`users_AFTER_INSERT` AFTER INSERT ON `users` FOR EACH ROW
BEGIN
UPDATE users SET uid = sha2(NEW.idusers, 256) WHERE idusers = NEW.idusers;
END $$
DELIMITER ;

How to prevent creation of records where the value of two fields is the same?

I have the following table.
CREATE TABLE people(
first_name VARCHAR(128) NOT NULL,
nick_name VARCHAR(128) NULL
)
I would like to prevent people from having their nickname be the same as their firstname if they attempt that insertion. I do not want to create an index on either of the columns just a rule to prevent the insertion of records where the first_name and nick_name are the same.
Is there a way to create a rule to prevent insertion of records where the first_name would equal the nick_name?
CREATE TRIGGER `nicknameCheck` BEFORE INSERT ON `people` FOR EACH ROW begin
IF (new.first_name = new.nick_name) THEN
SET new.nick_name = null;
END IF;
END
Or you can set first_name to NULL which will cause SQL error and you can handle it and show some warning.
You only need triggers for BEFORE INSERT and BEFORE UPDATE. Let these check the values and abort the operation, if they are equal.
Caveat: On older but still widely used versions of MySQL (before 5.5 IIRC) you need to do something bad, such as read from the written table or easier read from an inexistant table/column (in order to abort).
AFTER INSERT trigger to test and remove if same ...
CREATE TABLE ek_test (
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
one INT NOT NULL,
two INT NOT NULL
);
delimiter //
CREATE TRIGGER ek_test_one_two_differ AFTER INSERT ON ek_test
FOR EACH ROW
BEGIN
IF (new.one = new.two) THEN
DELETE FROM ek_test WHERE id = new.id;
END IF;
END//
delimiter ;
INSERT INTO ek_test (one, two) VALUES (1, 1);
SELECT * FROM ek_test;
NOTE you will also need AFTER UPDATE trigger.

MySQL trigger delete passing user ID

I need to create MySQL trigger that would log user ID on delete table row statement which must fit in one query, since I'm using PHP PDO. This is what I've come up so far:
I need the way to pass user ID in the delete query even though it is irrelevant to delete action to be performed:
Normally the query would look like this:
DELETE FROM mytable WHERE mytable.RowID = :rowID
If I could use multiple queries in my statement, I would do it like this:
SET #userID := :userID;
DELETE FROM mytable WHERE mytable.RowID = :rowID;
This way the variable #userID would be set before trigger event fires and it can use it. However since I need to squeeze my delete statement in one query, so I came up with this:
DELETE FROM mytable
WHERE CASE
WHEN #userID := :userID
THEN mytable.RowID = :rowID
ELSE mytable.RowID IS NULL
END
Just a note: RowID will never be null since it's the primary key. Now I have to create a delete trigger to log the user ID to the audit table, however I suppose that in this case trigger will be fired before the delete query itself which means that #userID variable will not be created? This was my idea of passing it as a value to the trigger.
I feel like I'm close to the solution, but this issue is a blocker. How to pass user ID value to the trigger without having multiple queries in the statement? Any thoughts, suggestions?
You can use NEW / OLD mysql trigger extensions. Reference: http://dev.mysql.com/doc/refman/5.0/en/trigger-syntax.html
Here is a sample code :
drop table `project`;
drop table `projectDEL`;
CREATE TABLE `project` (
`proj_id` int(11) NOT NULL AUTO_INCREMENT,
`proj_name` varchar(30) NOT NULL,
`Proj_Type` varchar(30) NOT NULL,
PRIMARY KEY (`proj_id`)
);
CREATE TABLE `projectDEL` (
`proj_id` int(11) NOT NULL AUTO_INCREMENT,
`proj_name` varchar(30) NOT NULL,
`Proj_Type` varchar(30) NOT NULL,
PRIMARY KEY (`proj_id`)
);
INSERT INTO `project` (`proj_id`, `proj_name`, `Proj_Type`) VALUES
(1, 'admin1', 'admin1'),
(2, 'admin2', 'admin2');
delimiter $
CREATE TRIGGER `uProjectDelete` BEFORE DELETE ON project
FOR EACH ROW BEGIN
INSERT INTO projectDEL SELECT * FROM project WHERE proj_id = OLD.proj_id;
END;$
delimiter ;
DELETE FROM project WHERE proj_id = 1;
SELECT * FROM project;
SELECT * FROM projectDEL;