sql >> Databasteknik >  >> RDS >> Mysql

MySQL:s INFOGA IGNORERA I &främmande nycklar

[NYTT SVAR]

Tack till @NeverEndingQueue för att du tog upp detta. Det verkar som att MySQL äntligen har åtgärdat det här problemet. Jag är inte säker på vilken version detta problem först fixades i, men just nu testade jag med följande version och problemet finns inte längre:

mysql> SHOW VARIABLES LIKE "%version%";
+-------------------------+------------------------------+
| Variable_name           | Value                        |
+-------------------------+------------------------------+
| innodb_version          | 5.7.22                       |
| protocol_version        | 10                           |
| slave_type_conversions  |                              |
| tls_version             | TLSv1,TLSv1.1                |
| version                 | 5.7.22                       |
| version_comment         | MySQL Community Server (GPL) |
| version_compile_machine | x86_64                       |
| version_compile_os      | Linux                        |
+-------------------------+------------------------------+

För att vara tydlig:

mysql> INSERT IGNORE INTO child
    -> VALUES
    ->     (NULL, 1)
    ->     , (NULL, 2)
    ->     , (NULL, 3)
    ->     , (NULL, 4)
    ->     , (NULL, 5)
    ->     , (NULL, 6);
Query OK, 4 rows affected, 2 warnings (0.03 sec)
Records: 6  Duplicates: 2  Warnings: 2

För att bättre förstå innebörden av den här sista frågan och varför den visar att problemet är löst, fortsätt med det gamla svaret nedan.

[GAMMEL SVAR]

Min lösning är att lösa problemet och den faktiska lösningen kommer alltid att vara att lösa problemet inom själva MySQL.

Följande steg löste mitt problem:

a. Överväg att ha följande tabeller och data:

mysql>
CREATE TABLE parent (id INT AUTO_INCREMENT NOT NULL
                     , PRIMARY KEY (id)
) ENGINE=INNODB;

mysql>
CREATE TABLE child (id INT AUTO_INCREMENT
                    , parent_id INT
                    , INDEX par_ind (parent_id)
                    , PRIMARY KEY (id)
                    , FOREIGN KEY (parent_id) REFERENCES parent(id)
                        ON DELETE CASCADE
                        ON UPDATE CASCADE
) ENGINE=INNODB;

mysql>
INSERT INTO parent
VALUES (NULL), (NULL), (NULL), (NULL), (NULL), (NULL);

mysql>
SELECT * FROM parent;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
|  5 |
|  6 |
+----+

b. Nu måste vi ta bort några av raderna för att visa problemet:

mysql>
DELETE FROM parent WHERE id IN (3, 5);

c. PROBLEM: Problemet uppstår när du försöker infoga följande underordnade rader:

mysql>
INSERT IGNORE INTO child
VALUES
    (NULL, 1)
    , (NULL, 2)
    , (NULL, 3)
    , (NULL, 4)
    , (NULL, 5)
    , (NULL, 6);

ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint f
ails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERE
NCES `parent` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)

mysql>
SELECT * FROM child;
Empty set (0.00 sec)

Även om IGNORE nyckelord används, men MySQL avbryter den begärda operationen eftersom det genererade felet inte omvandlas till varning (som det ska). Nu när problemet är uppenbart, låt oss se hur vi kan köra den sista infogningen i satsen utan att stöta på något fel.

d. LÖSNING: Jag kommer att slå in infogningen i en sats med några andra konstanta satser som varken är beroende av de infogade posterna eller deras antal.

mysql>
SET FOREIGN_KEY_CHECKS = 0;

mysql>
INSERT INTO child
VALUES
    (NULL, 1)
    , (NULL, 2)
    , (NULL, 3)
    , (NULL, 4)
    , (NULL, 5)
    , (NULL, 6);

mysql>
DELETE FROM child WHERE parent_id NOT IN (SELECT id FROM parent);

mysql>
SET FOREIGN_KEY_CHECKS = 1;

Jag vet att detta inte är optimalt men så länge MySQL inte har åtgärdat problemet är detta det bästa jag vet. Speciellt eftersom alla uttalanden kan köras i en begäran om du använder mysqli-biblioteket i PHP.



  1. Hur använder man alfanumeriska fält med BETWEEN-satsen i Mysql?

  2. Hur REPEAT() fungerar i MariaDB

  3. Ändring av datumformat i fråga

  4. Hur kan jag kopiera en enda rad/post från en MySQL-instans till en annan?