auto-increment value in update conflicts with internally generated values - mysql

I've been getting this error from an insert on duplicate update query in MYSQL randomly every now and then.
Any idea what's going on? I can't seem to reproduce the error consistently it occurs sometimes and then sometimes not.
Here is the query in question:
INSERT INTO friendships (u_id_1,u_id_2,status) VALUES (?,?,'active') ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id);
And the schema describing the table is:
DROP TABLE IF EXISTS `friendships`;
CREATE TABLE `friendships` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`u_id_1` int(11) NOT NULL,
`u_id_2` int(11) NOT NULL,
`status` enum('active','pending','rejected','blocked') DEFAULT 'pending' NOT NULL,
`initiatiator` enum('1','2','system') DEFAULT 'system' NOT NULL,
`terminator` enum('1','2','system') DEFAULT NULL,
`confirm_timestamp` timestamp DEFAULT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY (`u_id_1`,`u_id_2`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Your ON DUPLICATE KEY UPDATE statement isn't helping you at all here.
You are taking the LAST_INSERT_ID, which is the auto inc of the last successfully inserted row, and trying to update the duplicated row with that id. This will always cause a duplicate primary (you're trying to change the id of some row to match the id of the last thing you added)

If your goal is to either
Insert a new row, or
Update an existing row with 'active'
Then
INSERT INTO friendships (u_id_1,u_id_2,status)
VALUES ( ? , ? ,'active')
ON DUPLICATE KEY UPDATE
status = 'active'; -- I changed this

A separate consideration is to check the source for duplicates. I had a simple audit table
INSERT INTO table
field1, field2, ... , field3
ON DUPLICATE KEY UPDATE row_id=row_id;
where field1 is an INDEX but not UNIQUE with row_ID as INTEGER UNSIGNED AUTO_INCREMENT PRIMARY KEY.
Ran for years, but an unexpected duplicate row triggered this error.
Fixed by de-duping the source.
Possibly a trivial point to many readers here, but it cost me some head-scratching (followed by a facepalm).

Related

MySQL on duplicate key update is not updating

I'm trying to use on duplicate key update but it's not affecting any rows.
My table create statement, where you can see that I've created a unique key on childid and date.
CREATE TABLE `history_childfees` (
`childid` int(11) DEFAULT NULL,
`date` date DEFAULT NULL,
`amount` decimal(10,2) DEFAULT NULL,
`feetypecode` varchar(45) DEFAULT NULL,
UNIQUE KEY `key_childdate` (`childid`,`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
These are the two rows I have in the table.
The row I'm trying to update is the first row, by changing the amount for child 86615 on 2019-03-22.
insert into history_childfees (childid,date,amount,feetypecode)
values(86615,'2019-03-22',50,'DAY')
on duplicate key update childid = 86615, date = '2019-03-22';
I've also tried this syntax.
insert into history_childfees (childid,date,amount,feetypecode)
values (86615,'2019-03-22',50,'DAY')
on duplicate key update childid = values(childid), date = values(date);
Either way, it does not perform an insert and there's no error when I execute but it affects 0 rows. What am I missing here?
Consider:
CREATE TABLE `history_childfees` (
...
UNIQUE KEY `key_childdate` (`childid`,`date`)
);
And:
insert into history_childfees
...
on duplicate key update childid = 86615, date = '2019-03-22'
The columns that you update on duplicate key are exactly those of the UNIQUE KEY that you are using to identify duplicates. By design, we already know that the values do match... As a consequence, the query leaves duplicate records unmodified.
If I followed you correctly, you probably want:
insert into history_childfees
...
on duplicate key update amount = 50

How to suppress unique key checking while sql insert

I got a MySQL database with some tables.
In one of these tables i want to insert by a SQL script some new rows.
Unfortunately i have to insert in two columns an empty string and the two columns are part of an unique key for that table.
So i tried to set UNIQUE_CHECKS before and after the insert, but i'm getting errors because of duplicate entries.
Here is the definition of the table:
CREATE TABLE `Table_A` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`number` varchar(25) DEFAULT NULL,
`changedBy` varchar(150) DEFAULT NULL,
`changeDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`,`number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
And the INSERT statement which causes error:
SET UNIQUE_CHECKS = 0;
INSERT INTO `Table_A`
(`name`, `number`, `changedBy`, `changeDate`)
SELECT DISTINCT '', 'myUser', CURRENT_TIMESTAMP
FROM Table_A
AND id NOT IN
(
SELECT DISTINCT id
FROM Table_A
);
SET UNIQUE_CHECKS = 1;
As You can see, i'm using UNIQUE_CHECKS.
But as i said this doesn't work properly.
Any help or suggestion would be appreciated.
Patrick
Switching off Unique Keys for the insert operation doesn't indicate that it will check uniqueness only for the operations that happen after you switch it on again. It just means that database will not waste time to check the constraint during the time it is switch off but it will check the constraint when you switch it on again.
What it measn is that you nead to ensure that column has unique value in a columns with Unique Keys before you can turn it on. Which you don't do.
If you want to maintain Uniqueness somehow for new records you insert after some point in time you would need to create trigger and manually check the new records against already existing data. The same possibly goes for updates. But I don't recommend it - you should probably redesign data so either the Unique Key is not there or the data is truly unique for all the records there are and will be.

INSERT INTO ... ON DUPLICATE KEY UPDATE

i want to log timestamp, parameter_id and value into my db, using the timestamp and the parameter_id as the primary, unique key.
data_togo, CREATE TABLE 'data_togo' (
'id_para' int(10) unsigned NOT NULL DEFAULT '0',
't_ns' bigint(20) unsigned NOT NULL DEFAULT '0',
'id_inst' smallint(6) NOT NULL DEFAULT '1',
'value' varchar(255) NOT NULL DEFAULT '',
'isanchor' tinyint(4) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY ('t_ns','id_para')
) ENGINE=InnoDB DEFAULT CHARSET=utf8
However in a very rare condition the case can happen where there are duplicate primary keys with different values.
INSERT INTO data_togo (id_para, t_ns, id_inst, value, is_anchor) VALUES ...
Is it possible to keep both rows and update the second timestamp (nanoseconds, so that would not matter) to +1?
EDIT: Problem: currently there is a bug where i get the data from, the timestamp is rounded to milliseconds with microseconds resolution and then brought into nanoseconds format. hence, if it goes badly both the DIFFERENT timestamps are rounded to the same value, which leads to a duplicate primary key.
I've found a solution that works for two times the same timestamp:
Transfer the whole thing into a stored procedure
If the row exists, insert it with the following statement:
INSERT INTO edl_dw.data_togo (id_para, t_ns, id_inst, value, isanchor)
VALUES(#id_para, #t_ns, #id_inst, #value, #anchor)
ON DUPLICATE KEY UPDATE t_ns= #t_ns-1;
Then insert another row into the table with the same content, but with insert ignore
INSERT IGNORE edl_dw.data_togo (id_para, t_ns, id_inst, value, isanchor)
VALUES(#id_para, #t_ns, #id_inst, #value, #anchor);
If the row already existed, the old row timestamp will be set 1 ns back, but the content is kept. Then the new row gets inserted after that.
If the row didn't exist, the row get's inserted in the first statement, and the second insert gets ignored because the primary key already exists.

MySQL stop inserting when duplicate key condition is met

I have a table constructed by the followinng:
CREATE TABLE IF NOT EXISTS test_table (
ID int(11) NOT NULL AUTO_INCREMENT,
ProfileID int(11) NOT NULL,
ForeignID int(11) NOT NULL,
PRIMARY KEY (ProfileID,ForeignID) )
ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
I want to do something a little peculiar though, say there are 4 records in the database:
RecA, RecB, RecC, RecD
I would like to run the following query and have the insert behavior stop when a duplicate key was encountered:
INSERT IGNORE INTO test_table (ProfileID, ForeignID) VALUES(RecE, RecF, RecA, RecB, RecG);
So the query would only insert RecE and RecF, is there a way to do this in MySQL, perhaps using ON DUPLICATE KEY? Ideally the execution would just be terminated once a duplicate has been found, I am not too familiar with SQL syntax though.
Where RecG was explicitly not inserted.

MySQL Duplicate primary key on unexisting key

I've got a weird problem on a MySQL table. When trying to insert a new row, it says the primary key is duplicate. My primary key is auto incremental and is not set within my query (automatically set by MySQL).
The problem is I get a "Duplicate primary key" error on a key that doesn't even exists (I checked). I solved the problem increasing the current auto_increment value but I can't understand how it happened.
Any help would be great.
Edit
Table creation
CREATE TABLE `articles_mvt` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`ext_article_id` int(5) NOT NULL,
`date_mvt` date NOT NULL,
`qte` float(4,2) NOT NULL,
`in_out` enum('in','out') NOT NULL,
`ext_nateco_id` int(5) NOT NULL,
`ext_agent_id` int(5) NOT NULL COMMENT 'Demandeur',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1647 ;
Problematic query
INSERT INTO articles_mvt (
`ext_article_id`,
`date_mvt`,
`qte`,
`in_out`,
`ext_nateco_id`,
`ext_agent_id`
)
VALUES (
'".$_POST["numArticle"]."',
'".dateSql($_POST["date_mvt"])."',
".$_POST["qte_entier"].".".$_POST["qte_virgule"].",
'".$_POST["in_out"]."',
".$_POST["numNateco"].",
".$_POST["demandeur"]."
)
FYI variables are sanitized earlier in the code ;)
Well i think at that time you did not check auto Inc flag on primary key. So when you try to enter than value 0 is insert in the primary key and for second entry it gives error. like that
ID Value
0 A ok it not give error
0 ff it gives error..
Or you may try to insert a row whose ID is already exist like
ID Value
11 A ok it not give error
11 ff it gives error..