MySQL ON UPDATE CASCADE not CASCADEing - mysql
Suppose i have two below table:
CREATE TABLE post (
id bigint(20) NOT NULL AUTO_INCREMENT,
text text ,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=1;
CREATE TABLE post_path (
ancestorid bigint(20) NOT NULL DEFAULT '0',
descendantid bigint(20) NOT NULL DEFAULT '0',
length int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (ancestorid,descendantid),
KEY descendantid (descendantid),
CONSTRAINT f_post_path_ibfk_1
FOREIGN KEY (ancestorid) REFERENCES post (id)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT f_post_path_ibfk_2
FOREIGN KEY (descendantid) REFERENCES post (id)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB;
And inserted these rows:
INSERT INTO
post (text)
VALUES ('a'); #// inserted row by id=1
INSERT INTO
post_path (ancestorid ,descendantid ,length)
VALUES (1, 1, 0);
When i want to update post row id:
UPDATE post SET id = '10' WHERE post.id =1
MySQL said:
#1452 - Cannot add or update a child row: a foreign key constraint fails (test.post_path, CONSTRAINT f_post_path_ibfk_2 FOREIGN KEY (descendantid) REFERENCES post (id) ON DELETE CASCADE ON UPDATE CASCADE)
Why? what is wrong?
Edit:
When i inserted these rows:
INSERT INTO
post (text)
VALUES ('b'); #// inserted row by id=2
INSERT INTO
post_path (ancestorid, descendantid, length)
VALUES (1, 2, 0);
And updated:
UPDATE post SET id = '20' WHERE post.id =2
Mysql updated successfully both child and parent row.
so Why i can not update first post (id=1)?
Ok, I ran your schema and queries through a test database I have access too and noticed the following; after inserting both rows to both tables, and before any updates the data looks like:
mysql> select * from post;
+----+------+
| id | text |
+----+------+
| 1 | a |
| 2 | b |
+----+------+
2 rows in set (0.00 sec)
mysql> select * from post_path;
+------------+--------------+--------+
| ancestorid | descendantid | length |
+------------+--------------+--------+
| 1 | 1 | 0 |
| 1 | 2 | 0 |
+------------+--------------+--------+
2 rows in set (0.00 sec)
After I issue the update statement, to update post.id to 20:
mysql> UPDATE `post` SET `id` = '20' WHERE `post`.`id` =2;
Query OK, 1 row affected (0.08 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from post_path;
+------------+--------------+--------+
| ancestorid | descendantid | length |
+------------+--------------+--------+
| 1 | 1 | 0 |
| 1 | 20 | 0 |
+------------+--------------+--------+
2 rows in set (0.00 sec)
Notice that the ancestorid is still 1, this appears to be an issue with MySQL:
If you use a multiple-table UPDATE statement involving InnoDB tables for which there are foreign key constraints, the MySQL optimizer might process tables in an order that differs from that of their parent/child relationship. In this case, the statement fails and rolls back. Instead, update a single table and rely on the ON UPDATE capabilities that InnoDB provides to cause the other tables to be modified accordingly. See Section 14.3.5.4, “InnoDB and FOREIGN KEY Constraints”.
The reason why your first query is failing, is because ancestorid is not updating to 10, but descendantid is, and because you are trying to set post.id to 10, and ancestorid in post_path table is still referencing the value 1, which would no longer exist.
You should consider altering your schema to avoid this, and to also avoid updating an auto_increment column so you avoid collisions.
I believe the solution to your problem is to remove descendantid as a constraint and use a trigger to perform an update on the field.
delimiter $$
CREATE TRIGGER post_trigger
AFTER UPDATE ON post
FOR EACH ROW
BEGIN
UPDATE post_path SET post_path.descendantid = NEW.id WHERE post_path.descendantid = OLD.id
END$$
The main reason why the second one worked is that you have kept different values for ancestorid and descendantid. When you are making two different constraints on the basis of a change on a particular attributes. only the first constraint will work, not the second one. Which is the case in your first update try.
The reason the first update fails and second does not is because in the second instance your ancestorid and descendantid reference different rows in your post table,
ancestorid = 1
descendantid = 2
The first update fails when it attempts to update post_path.ancestorid as in doing so the constraint between post.id and post_path.descendantid fails as these values would no longer match (1 !== 10).
Assuming that any given post cannot be both an ancestor and a descendant then the issue here is only in the execution of the first insert:
INSERT INTO `post_path` (`ancestorid` ,`descendantid` ,`length`) VALUES (1, 1, 0);
Related
SELECT LIMIT 1 query returns unexpected results when the queried table field has an index
I have a table with an id field and some other fields. The id field has an index by default and this index seems to cause problems when i try to return the id value of the first row using the following query with a limit 1 clause: SELECT cropvarietyname.id FROM `seedcalendar-test`.cropvarietyname LIMIT 1; The first row has 1 as the id but instead of returning the value 1 this query returns the value 73. The row with id 73 is definitely not the first row! When i use EXPLAIN to analyze this query i get the following result: id, select_type, table, partitions, type, possible_keys, key, key_len, ref, rows, filtered, Extra '1', 'SIMPLE', 'cropvarietyname', NULL, 'index', NULL, 'IDX_crop', '8', NULL, '433', '100.00', 'Using index' For some reason the primary key index of id is used when running this query and it causes the id of row 73 to be returned instead of 1. When i replace the field id with a field that doesn't have an index (lastModified in the example below) then the field value of the first row is returned. So the following does work: SELECT cropvarietyname.lastModified FROM `seedcalendar-test`.cropvarietyname LIMIT 1; When i look at the extra field of the explain query result for this select query i can see that in this case no index is used. The following also works: SELECT cropvarietyname.lastModified, cropvarietyname.id FROM `seedcalendar-test`.cropvarietyname LIMIT 1; Here one queried field has an index (id) and one doesn't (lastModified). When i run it the id and lastModified values of the first row are correctly returned. But as soon as the LIMIT query contains nothing but indexed fields MySQL starts returning unexpected results because it starts using the index for some reason. My question is: Why does this happen? There is no WHERE clause in the query so there should be no reason for MySQL to use one or more field indexes when executing this query. This problem can be resolved by adding ORDER BY cropvarietyname.id ASC right before the LIMIT 1 clause. But i don't understand why i need to do this in the first place. Why doesn't MySQL return the value(s) of the first row when all the queried fields happen to be indexed and why does it suddenly start working correctly when you introduce atleast one unindexed field to the SELECT list? Below is the code to recreate the table i've used in my examples. Although i must add that the same strange behavior can be seen when running a LIMIT query with an indexed field on any table. CREATE TABLE `cropvarietyname` ( `id` bigint(20) NOT NULL, `dateCreated` datetime DEFAULT NULL, `lastModified` datetime DEFAULT NULL, `lastAssessedOn` datetime DEFAULT NULL, `deleted` bit(1) NOT NULL, `submissionStatus` int(11) NOT NULL, `translatedName` varchar(255) DEFAULT NULL, `scientificName` varchar(255) DEFAULT NULL, `assessor_id` bigint(20) DEFAULT NULL, `language_id` bigint(20) NOT NULL, `user_id` bigint(20) NOT NULL, `FK_CROP` bigint(20) NOT NULL, `parent_id` bigint(20) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `UC_parent_id_language_id_translatedName` (`parent_id`,`translatedName`,`language_id`), KEY `IDX_scientific_name` (`scientificName`), KEY `IDX_crop` (`FK_CROP`), KEY `IDX_name_crop` (`translatedName`,`FK_CROP`), KEY `IDX_cropvariety` (`parent_id`), KEY `IDX_cropvariety_language` (`language_id`,`parent_id`), KEY `IDX_submissionStatus_language` (`language_id`,`submissionStatus`), KEY `IDX_name_scientific_name` (`translatedName`,`scientificName`), KEY `IDX_crop_language` (`FK_CROP`,`language_id`), KEY `IDX_translator` (`user_id`), KEY `IDX_name_language` (`translatedName`,`language_id`), KEY `FKs7a71sapplqu96ntraxjen1f0` (`assessor_id`), CONSTRAINT `FK5veqd7kl96d3dj14uqs5w3atd` FOREIGN KEY (`parent_id`) REFERENCES `cropvariety` (`id`) ON DELETE CASCADE, CONSTRAINT `FK8hlx1suats5c60n5mcs2meue6` FOREIGN KEY (`user_id`) REFERENCES `members` (`id`), CONSTRAINT `FK99c5ih7r49epis56k3buksvv1` FOREIGN KEY (`FK_CROP`) REFERENCES `crop` (`id`) ON DELETE CASCADE, CONSTRAINT `FKb536j3ril2noa5lepafnv7vc5` FOREIGN KEY (`language_id`) REFERENCES `languages` (`id`), CONSTRAINT `FKs7a71sapplqu96ntraxjen1f0` FOREIGN KEY (`assessor_id`) REFERENCES `members` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 After you've created the table you can use the following test data to populate it with. These insert statements only give you the first 17 rows of the entire test dataset of 433 rows but it should be enough to reproduce the problem: INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (1,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'green cactus 5 30other2','31-1100583337',NULL,1,4,7,1); INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (2,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'cactus vert 5 30','31927763221',NULL,21,4,7,1); INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (3,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'green cactus 5 30','31826800418',NULL,1,4,7,1); INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (4,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'green cactus 5 30other1','31-2130733867',NULL,1,4,7,1); INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (5,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'grunne kaktus 5 30other1','31124416021',NULL,25,4,7,1); INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (6,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'grunne kaktus 5 30','311170713725',NULL,25,4,7,1); INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (7,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'groene cactus 5 30other1','314209744',NULL,17,4,7,1); INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (8,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'groene cactus 5 30','31-1824444332',NULL,17,4,7,1); INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (9,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'cactus vert 5 30other2','31555292418',NULL,21,4,7,1); INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (10,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'grunne kaktus 5 30other2','31-736042183',NULL,25,4,7,1); INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (11,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'cactus vert 5 30other1','31459711790',NULL,21,4,7,1); INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (12,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'groene cactus 5 30other2','31458401709',NULL,17,4,7,1); INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (13,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'basilic 7 30other1','311174402979',NULL,21,4,6,2); INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (14,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'basilikum 7 30','311067296650',NULL,25,4,6,2); INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (15,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'basel 7 30','311648762313',NULL,1,4,6,2); INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (16,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'bascilicum 7 30','31-1839617752',NULL,17,4,6,2); INSERT INTO `` (`id`,`dateCreated`,`lastModified`,`lastAssessedOn`,`deleted`,`submissionStatus`,`translatedName`,`scientificName`,`assessor_id`,`language_id`,`user_id`,`FK_CROP`,`parent_id`) VALUES (17,'2022-08-16 23:05:29','2022-08-16 23:05:29',NULL,'0',4,'basel 7 30other2','31-2027625143',NULL,1,4,6,2); EDIT: I am using MySQL 8.
It is a bug in your code to do selects without specifying an ORDER BY and expect some particular order. Conceptually, database tables are unordered data; there is no "first row". The database is free to return rows in any order it wants, and seemingly unrelated changes to your query may change that order, as can changing database versions.
In practice, current versions of InnoDB reads rows in order by the index it uses to access the table. If no index is used, it reads the rows in order by the clustered index (that is, the primary key order). Demo: I create a table that has a clustered index (id) and another indexed column (x), and another non-indexed column (y). mysql> create table test (id serial primary key, x int, y int, key(x)); I fill 3 rows, such that the order of the primary key is opposite the order of the other rows: mysql> insert into test values (1, 6, 13), (2, 5, 12), (3, 4, 11); If I query all the columns without specifying an order, they are returned in primary key order: mysql> select * from test; +----+------+------+ | id | x | y | +----+------+------+ | 1 | 6 | 13 | | 2 | 5 | 12 | | 3 | 4 | 11 | +----+------+------+ If I query only the unindexed column y, they are also returned in primary key order: mysql> select y from test; +------+ | y | +------+ | 13 | | 12 | | 11 | +------+ If I query only the indexed column x, the rows are read from the index on x, and are returned in that order: mysql> select x from test; +------+ | x | +------+ | 4 | | 5 | | 6 | +------+ If I query the indexed column x with the primary key, the rows are still returned in the order of x: mysql> select id, x from test; +----+------+ | id | x | +----+------+ | 3 | 4 | | 2 | 5 | | 1 | 6 | +----+------+ Why is that? EXPLAIN can show us: mysql> explain select id, x from test\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: test partitions: NULL type: index possible_keys: NULL key: x key_len: 5 ref: NULL rows: 3 filtered: 100.00 Extra: Using index The key field of the EXPLAIN shows us that it's reading from the index x. InnoDB indexes always contain the primary key value, so in this case there's no need for MySQL to read anything but the index. All these internal rules can be difficult to remember. It's a much better idea to use an ORDER BY clause to be explicit if you need the rows to be returned in a particular order. The query engine may still read the rows in whatever order the storage engine chooses, but it will re-sort them if necessary before returning the result set.
Bottom line: Always use ORDER BY to get predictability. Your 4 cases (plus 1), and assuming PRIMARY KEY (id) and in_no_index does not show up in any INDEX): SELECT id ... WHERE id=1 LIMIT 1 -- 1 SELECT id ... LIMIT 1 -- 2 SELECT in_no_index ... LIMIT 1 -- 3 SELECT in_no_index, id ... LIMIT 1 -- 4 SELECT in_some_index, id ... LIMIT 1 -- 5 1: Since id is UNIQUE (because of being the PK), the LIMIT is irrelevant; the one row with id=1 is delivered. 2,5: (Surprise!) In InnoDB, secondary keys implicitly include a copy of the PK. Hence any index can be used. The Optimizer may pick the "smallest" index. You get a rather random result. 3,4: The Optimizer has no reasonable choice other than to scan the table. Hence, it delivers the column for the "first" row. Since InnoDB always orders the data BTree by the PK, that will be the row with the smallest id. Further note: Using ORDER BY does not necessarily take any extra effort. It depends on whether the Optimizer can eliminate the sorting when it is using an INDEX.
MySQL auto increment value set to zero
Here is a table CREATE TABLE `mytable` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `val` char(128) NOT NULL DEFAULT '', PRIMARY KEY (`id`), UNIQUE KEY (val) ) ENGINE=InnoDB DEFAULT CHARSET=ascii; Any idea why is this happening, I expected it to set id to zero in the first query itself MariaDB > insert into mytable set id=0, val="" on duplicate key update id=0, val=val; Query OK, 1 row affected (0.01 sec) MariaDB > select * from mytable; +----+-------+ | id | val | +----+-------+ | 1 | | +----+-------+ 1 row in set (0.00 sec) MariaDB > insert into mytable set id=0, val="" on duplicate key update id=0, val=val; Query OK, 2 rows affected (0.01 sec) MariaDB > select * from mytable; +----+-------+ | id | val | +----+-------+ | 0 | | +----+-------+ 1 row in set (0.00 sec) MariaDB > insert into mytable set id=0, val="" on duplicate key update id=0, val=val; Query OK, 0 rows affected (0.01 sec) Any explanation will be appreciated. Update: I am aware of using AUTO_INCREMENT=0 but the real question here is that query explicitly set id=0, so why it is setting it as 1 in first query. It seems mysql ok to set it 0 in duplicate instance. Thanks
When inserting a new record, setting an AUTO_INCREMENT column to 0 means "generate a new value for this column" (ref). Values for AUTO_INCREMENT columns start from 1. Thus: insert into mytable set id=0, val="" on duplicate key update id=0, val=val; is equivalent to: insert into mytable set id=1, val=""; The second insert you call would create a duplicate key (for the val field, not the id field). This causes the update statement to be run, thus updating id to zero. The "2 rows affected" message appears because the on duplicate key update statement returns 2 in case an existing row is updated (ref). The third insert does nothing. Both keys are duplicate, but the existing row doesn't need to be updated because its values are already what you expect them to be. In this case the on duplicate key update statement returns "0 rows affected".
By default, the starting value for AUTO_INCREMENT is 1, and it will increment by 1 for each new record. To let the AUTO_INCREMENT sequence start with another value, use the following SQL statement: ALTER TABLE myTabel AUTO_INCREMENT=0; Credits
The answer about NO_AUTO_VALUE_ON_ZERO is correct, although a bit incomplete. There is an option to sql_mode to allow for an explicit value of zero to be entered in an autoincrement field. By default 0 is treated the same as null. If you add the NO_AUTO_VALUE_ON_ZERO option, you are allowed to specify a zero value in that field. I have this in my cnf file: sql_mode='NO_AUTO_VALUE_ON_ZERO,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'
please check NO_AUTO_VALUE_ON_ZERO option. By default, auto_increment column cannot be inserted zero value. If you set NO_AUTO_VALUE_ON_ZERO on, you can force to input auto_increment column zero value.
INSERT INTO or UPDATE with two conditions
This problem seems easy at first sight, but I simply have not found a solution that is reasonable time wise. Consider a table with the following characteristics: ID INTEGER PRIMARY KEY AUTOINCREMENT name INTEGER values1 INTEGER values2 INTEGER dates DATE Every day, N amount of new rows are generated, for dates into the future, and with the 'name' coming from a finite list. I would like to insert a new row when there is new data, but if there is already a row with 'name' and 'dates', simply update it. Please note that a current proposed solution of an SPROC that checks the conditional is not feasible, as this is data being pushed from another language.
that is what insert on duplicate key update is for. The Manual page for it is here. The trick is that the table needs to have a unique key (can be a composite) so that the clash of doing an insert can be detected. As such, the update to occur on that row, otherwise an insert. It can be a primary key, of course. In your case, you could have a composite key such as unique key(theName,theDate) If the row is already there, the clash is detected, and the update happens. Here is a complete example create table myThing ( id int auto_increment primary key, name int not null, values1 int not null, values2 int not null, dates date not null, unique key(name,dates) -- <---- this line here is darn important ); insert myThing(name,values1,values2,dates) values (777,1,1,'2015-07-11') on duplicate key update values2=values2+1; insert myThing(name,values1,values2,dates) values (778,1,1,'2015-07-11') on duplicate key update values2=values2+1; -- do the 1st one a few more times: insert myThing(name,values1,values2,dates) values (777,1,1,'2015-07-11') on duplicate key update values2=values2+1; insert myThing(name,values1,values2,dates) values (777,1,1,'2015-07-11') on duplicate key update values2=values2+1; insert myThing(name,values1,values2,dates) values (777,1,1,'2015-07-11') on duplicate key update values2=values2+1; show results select * from myThing; +----+------+---------+---------+------------+ | id | name | values1 | values2 | dates | +----+------+---------+---------+------------+ | 1 | 777 | 1 | 4 | 2015-07-11 | | 2 | 778 | 1 | 1 | 2015-07-11 | +----+------+---------+---------+------------+ As expected, insert on duplicate key update works, just 2 rows.
This is easy: Create a unique key on the columns to check Use the INSERT .. ON DUPLICATE KEY UPDATE construct
The insert APPEARS to work, but doesn’t in mysql
this is a very strange issue... select count(*) from imprint_users; count 461 INSERT INTO coresource.imprint_users (imprint_sid, users_sid) VALUES (2387,165); Query OK, 1 row affected (0.00 sec) select count(*) from imprint_users; count 461 1) cannot see anything in mysql-error 2) checked the status of the table just in case +--------------------------+-------+----------+----------+ | Table | Op | Msg_type | Msg_text | +--------------------------+-------+----------+----------+ | coresource.imprint_users | check | status | OK | +--------------------------+-------+----------+----------+ 3)here is the create statement CREATE TABLE "imprint_users" ( "imprint_sid" bigint(20) NOT NULL, "users_sid" bigint(20) NOT NULL, PRIMARY KEY ("imprint_sid","users_sid"), KEY "FK__IMPRINT_U__IMPRI__47E69B3D" ("imprint_sid"), KEY "FK__IMPRINT_U__USERS__48DABF76" ("users_sid"), CONSTRAINT "fk__imprint_u__impri__47e69b3d" FOREIGN KEY ("imprint_sid") REFERENCES "imprint" ("imprint_sid"), CONSTRAINT "fk__imprint_u__users__48dabf76" FOREIGN KEY ("users_sid") REFERENCES "users" ("users_sid") ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci | 4) This is in a M-M setup and we are writing to M1 Server version: 5.6.24-72.2-log Percona Server (GPL), Release 72.2, Any help or direction would be appreciated.
try a test. first you flush table & autocommit is set to zero then set it to 1. flush table; set #autocommit=1; select count(*) from imprint_users; INSERT INTO coresource.imprint_users (imprint_sid, users_sid) VALUES (2387,165); select count(*) from imprint_users; If still the problem remains then see is there any TRIGGER OR EVENT working in background. So disable all triggers, disable the entire scheduler (all events)- SET #disable_triggers = 1; SET #event_scheduler = OFF; run the query & test
Foreign key and the primary key in the same table
I need to create a relationship between two attributes in the same table. So both primary key and the foreign keys are in the same table. Here I have a table called User_Type. Primary key is User_ID. It should be the foreign key of Parent_ID. Ex: User_Type User_ID User_Name Parent_ID User_Type_Division But when I'm creating the relationship I get an error like this. Cannot add or update a child row: a foreign key constraint fails (mydb.user_type, CONSTRAINT Parent_User_Type FOREIGN KEY (Parent_ID) REFERENCES user_type (User_ID) ON DELETE NO ACTION ON UPDATE NO ACTION)"). Is there any way available to avoid this error. Please someone let me know. And Here I have given the Query of the table. CREATE TABLE IF NOT EXISTS `user_type` ( `User_ID` int(11) NOT NULL AUTO_INCREMENT, `User_Name` varchar(45) NOT NULL, `Parent_ID` int(11) DEFAULT NULL, `User_Type_Division` varchar(45) DEFAULT NULL, `User_ID_Format` varchar(45) DEFAULT NULL, `Data_Entered_Person` varchar(45) DEFAULT NULL, `Entered_Time` varchar(45) DEFAULT NULL, PRIMARY KEY (`User_ID`), UNIQUE KEY `User_Name_UNIQUE` (`User_Name`), KEY `ParentUserType` (`Parent_ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
There is a way to add and enforce foreign key on existing data. Step 1: You need to stop foreign key checks for the current session. SET FOREIGN_KEY_CHECKS=0; Step 2: Add foreign key to your table. ALTER TABLE myTable ADD CONSTRAINT fk_name FOREIGN KEY ( columnName ) REFERENCES ... Step 3: Enable foreign key checks. SET FOREIGN_KEY_CHECKS=1; Working Example: mysql> create table fkchk( i int not null primary key auto_increment, n int ); Query OK, 0 rows affected (0.26 sec) mysql> insert into fkchk(n) values ( 0 ); Query OK, 1 row affected (0.10 sec) mysql> show variables like '%fore%'; +--------------------+-------+ | Variable_name | Value | +--------------------+-------+ | foreign_key_checks | ON | +--------------------+-------+ 1 row in set (0.00 sec) mysql> alter table fkchk > add constraint fk_n foreign key (n) references fkchk(i) > on delete no action; ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.<result 2 when explaining filename '#sql-6fc_14'>, CONSTRAINT `fk_n` FOREIGN KEY (`n`) REFERENCES `fkchk` (`i`) ON DELETE NO ACTION) mysql> SET FOREIGN_KEY_CHECKS=0; Query OK, 0 rows affected (0.00 sec) mysql> show variables like '%fore%'; +--------------------+-------+ | Variable_name | Value | +--------------------+-------+ | foreign_key_checks | OFF | +--------------------+-------+ 1 row in set (0.00 sec) mysql> alter table fkchk > add constraint fk_n foreign key (n) references fkchk(i) > on delete no action; Query OK, 0 rows affected (0.50 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> insert into fkchk(n) values ( 0 ); Query OK, 1 row affected (0.32 sec) mysql> select * from fkchk; +---+------+ | i | n | +---+------+ | 1 | 0 | | 2 | 0 | +---+------+ 2 rows in set (0.00 sec) mysql> SET FOREIGN_KEY_CHECKS=1; Query OK, 0 rows affected (0.00 sec) mysql> show variables like '%fore%'; +--------------------+-------+ | Variable_name | Value | +--------------------+-------+ | foreign_key_checks | ON | +--------------------+-------+ 1 row in set (0.00 sec) mysql> insert into fkchk(n) values ( 1 ); Query OK, 1 row affected (0.12 sec) mysql> insert into fkchk(n) values ( 0 ); ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`fkchk`, CONSTRAINT `fk_n` FOREIGN KEY (`n`) REFERENCES `fkchk` (`i`) ON DELETE NO ACTION) mysql> mysql> select * from fkchk; +---+------+ | i | n | +---+------+ | 1 | 0 | | 2 | 0 | | 3 | 1 | +---+------+ 3 rows in set (0.00 sec) mysql>
Double check that the User_ID column and the Parent_ID column are of the same datatype. Also, your User_ID key column is set to NOT NULL, but your Parent_ID column is set to null. that could be the problem. Set Parent_ID to NOT NULL and then try creating the FK relationship again. This is one of the options I was talking about. However, if you already have data in your table, this could be an issue too.