INSERT INTO... ON DUPLICATE KEY UPDATE ... IF - mysql

I'm stuck on this one INSERT INTO for my school assignment.
INSERT INTO leaderboardeasy VALUES("Patrik", 15.44, 2021-04-24)
ON DUPLICATE KEY UPDATE IF(15.44 < Ido) Ido=15.44, Datum=2021-04-24
The 15.44 is a PHP variable.Basically I want insert into the table, if it not exists, and if it exists, and if the PHP variable(in this case 15.44 is smaller than the corresponding row(Ido) ) then I want to update the Ido, and Datum(current date) of the duplicate key.
What is the problem with my query?

you have a basic problem that dates have to be in single qiotes.
the if statement is not like mysql work,.
But i don't know if that reaöly makes what you want.
Because this would only run when Patrick is a primary key or a unique
INSERT INTO leaderboardeasy VALUES("Patrik", 15.44, '2021-04-24')
ON DUPLICATE KEY UPDATE Ido = IF(15.44 < Ido,15.44,Ido) , Datum=VALUES(Datum)
Better is a trigger
CREATE TRIGGER before_leaderboardeasy_insert
BEFORE INSERT
ON leaderboardeasy FOR EACH ROW
BEGIN
IF NEW.Ido > 15.44 THEN
SET NEW.Ido = 15.44;
END IF;
END $$
DELIMITER ;

If I understood you correctly your goal for the if statement is if the IF condition is met to update ido and datum to the given values, and otherwise not to update them and keep them intact. If this is the case:
INSERT INTO leaderboardeasy
VALUES("Patrik", 15.44, '2021-04-24')
ON DUPLICATE KEY UPDATE
`Ido` = CASE
WHEN (15.44 < `Ido`) THEN 15.44
ELSE `Ido`
END,
`Datum` = CASE
WHEN (15.44 < `Ido`) THEN '2021-04-24'
ELSE `Datum`
END

Related

How to add unique random values to the column in mysql

I want to add 1000 unique random values to the column AgentID to the table agents.
I have used Upsert to ignore the duplicate values. What I have done so far:
DROP PROCEDURE IF EXISTS Generate_random;
DELIMITER $$
CREATE PROCEDURE Generate_random()
BEGIN
Drop table if exists ai_training.`Agents`;
CREATE TABLE ai_training.`Agents`(AgentID int PRIMARY KEY);
SET #first = 1;
SET #last = 1000;
WHILE(#first <= #last) Do
INSERT INTO ai_training.`Agents` VALUES(
FLOOR(RAND()*(2900000-2800000+1)+2800000)
)
ON DUPLICATE KEY UPDATE AgentID = FLOOR(RAND()*(2900000-2800000+1)+2800000);
SET #first = #first + 1;
END WHILE;
END$$
DELIMITER ;
CALL Generate_random();
Select * from ai_training.`Agents`;
The problem is I need 1000 unique agentid's and this code is generating 1000 - the repeated ones. So, if it finds 6 repeated ids it returns 994 rows and not 1000.
Is there any way I can achieve this?
Can't change the random ID generation part.
You could use information function ROW_COUNT() to check whether a row was actually inserted or not, and increment the counter accordingly.
The documentation states:
With ON DUPLICATE KEY UPDATE, the affected-rows value per row is 1 if the row is inserted as a new row, 2 if an existing row is updated, and 0 if an existing row is set to its current values.
So:
WHILE(#first <= #last) DO
INSERT INTO ai_training.`Agents`
VALUES(FLOOR(RAND()*(2900000-2800000+1)+2800000))
ON DUPLICATE KEY UPDATE AgentID = AgentID;
IF ROW_COUNT() = 1 THEN
SET #first = #first + 1;
END IF;
END WHILE;
Note that I changed the action on duplicate key to a dummy update rather than re-assigning a new random value; this makes things a little less expensive when a collision happens.
CREATE PROCEDURE Generate_random()
BEGIN
Drop table if exists ai_training.`Agents`;
CREATE TABLE ai_training.`Agents`(AgentID int PRIMARY KEY);
SET #last = 1000;
WHILE (SELECT COUNT(*) FROM ai_training.`Agents`) < #last DO
INSERT IGNORE INTO ai_training.`Agents`
VALUES
(FLOOR(RAND()*(2900000-2800000+1)+2800000));
END WHILE;
END

Deleting row on trigger before insert, with on duplicate update

Situation
I am saving modifications done on users' profiles (for a logging purpose).
I am using this query to insert/update in a :
INSERT INTO infos_update (username, date_modif, column_name, old_value, new_value)
VALUES ('johnsmith', CURDATE(), 'department', 'Management', 'IT/IS')
ON DUPLICATE KEY UPDATE new_value='IT/IS, date_modif=CURDATE()
The primary key is composed of date_modif, username, column_name, where date is a date and not a datetime.
Goal
I want to use a trigger to avoid logging values that did not changed (where old_value and new_value are equals)
delimiter //
CREATE TRIGGER before_insert_infos_update
BEFORE INSERT ON infos_update FOR EACH ROW
BEGIN
IF NEW.old_value = NEW.new_value THEN
DELETE FROM infos_update
WHERE infos_update.username= NEW.username
AND infos_update.date_modif = NEW.date_modif
AND infos_update.column_name = NEW.column_name;
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Values are the same';
END IF;
END\\`
It prevents duplicates on initial insert, but when the row is already inserted, on duplicate key update can still update rows with duplicate old and new values; even when simply deleting the row before the update with that trigger

IF NOT EXISTS in mysql showing syntax error

I am trying to convert this tsql to mysql but showing error need help
CREATE PROCEDURE FormAdd
#formName varchar(MAX)
AS
IF NOT EXISTS(SELECT * FROM tbl_Form WHERE formName=#formName)
BEGIN
INSERT INTO tbl_Form
(formName)
VALUES
(#formName)
SELECT ##identity
END
ELSE
BEGIN
SELECT '-1'
END
mysql
CREATE PROCEDURE FormAdd
(p_formName varchar(500) )
begin
INSERT INTO tbl_Form (formName)
VALUES (p_formName)
where NOT EXISTS(SELECT * FROM tbl_Form WHERE formName=p_formName) ;
SELECT Last_insert_id() as returnvalue ;
SELECT '-1' ;
end
Your attempt was syntactically invalid because logically, an INSERT statement cannot contain a WHERE clause since it does not act on existing rows.
If the purpose is to insert only if the value for p_formname is not already present, then an appropriate step would be to define a unique index on that column first. Then, construct your procedure to attempt the insert and inspect the ROW_COUNT() value to see if one was inserted and act accordingly, returning -1 if not to adapt your existing T-SQL procedure.
First create the unique index on p_formname:
ALTER TABLE tbl_Form ADD UNIQUE KEY `idx_formName` (`formName`);
Then your procedure should use INSERT INTO...ON DUPLICATE KEY UPDATE to attempt to insert the row. Per the documentation, the value of ROW_COUNT() will be 0 if a new row was not inserted or 1 if it was.
CREATE PROCEDURE FormAdd (p_formName varchar(500))
BEGIN
/* Attempt the insert, overwrite with the same value if necessary */
INSERT INTO tbl_Form (formName) VALUES (p_formName) ON DUPLICATE KEY UPDATE formName = p_formName;
/* Return the LAST_INSERT_ID() for a new row and -1 otherwise */
SELECT
CASE
WHEN ROW_COUNT() = 1 THEN LAST_INSERT_ID()
ELSE -1
END AS returnValue;
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

mysql trigger error with 2 conditions

I want to add an after insert trigger which will do the following.
The first IF condition works normally, but when it comes to the second everything stops.
Any ideas?
USE `Syslog`;
DELIMITER $$
CREATE TRIGGER `SystemEventsR_AINS` AFTER INSERT ON SystemEventsR FOR EACH ROW
IF
(exists
(select syslogtag from SystemEventsRcounter where syslogtag=
new.syslogtag)
AND
(select simpledate from SystemEventsRcounter
where syslogtag=new.syslogtag)=new.simpledate)
THEN
UPDATE SystemEventsRcounter
SET records=records+1
WHERE SystemEventsRcounter.syslogtag=new.syslogtag;
ELSE INSERT SystemEventsRcounter (simpledate, syslogtag, records) values (new.simpledate,new.syslogtag,1);
END IF
UPDATED:
What you need is INSERT INTO ... ON DUPLICATE KEY.
CREATE TRIGGER `SystemEventsR_AINS`
AFTER INSERT ON SystemEventsR
FOR EACH ROW
INSERT INTO SystemEventsRcounter (simpledate, syslogtag, records)
VALUES (NEW.simpledate, NEW.syslogtag, 1)
ON DUPLICATE KEY UPDATE records = records + 1;
In order for it to work you need to create a unique composite index on (simpledate, syslogtag)
CREATE UNIQUE INDEX idx_u_simpledate_syslogtag
ON SystemEventsRcounter (simpledate, syslogtag);
Here is SQLFiddle demo.
If you wanted it your way then it might look like
DELIMITER $$
CREATE TRIGGER `SystemEventsR_AINS`
AFTER INSERT ON SystemEventsR
FOR EACH ROW
BEGIN
IF (
SELECT COUNT(*) simpledate
FROM SystemEventsRcounter
WHERE syslogtag = NEW.syslogtag
AND simpledate = NEW.simpledate
) > 0 THEN
UPDATE SystemEventsRcounter
SET records = records + 1
WHERE SystemEventsRcounter.syslogtag = NEW.syslogtag;
ELSE
INSERT INTO SystemEventsRcounter (simpledate, syslogtag, records)
VALUES (NEW.simpledate, NEW.syslogtag, 1);
END IF;
END$$
DELIMITER ;
Here is SQLFiddle demo.