Mysql
 sql >> Datenbank >  >> RDS >> Mysql

INSERT IGNORE INTO &Fremdschlüssel von MySQL

[NEUE ANTWORT]

Danke an @NeverEndingQueue, dass du das angesprochen hast. Es scheint, dass MySQL dieses Problem endlich behoben hat. Ich bin mir nicht sicher, in welcher Version dieses Problem zuerst behoben wurde, aber im Moment habe ich mit der folgenden Version getestet und das Problem besteht nicht mehr:

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                        |
+-------------------------+------------------------------+

Um es klar zu sagen:

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

Um die Bedeutung dieser letzten Abfrage besser zu verstehen und warum sie anzeigt, dass das Problem behoben ist, fahren Sie bitte mit der alten Antwort unten fort.

[ALTE ANTWORT]

Meine Lösung ist eine Umgehung des Problems und die eigentliche Lösung wird immer darin bestehen, das Problem innerhalb von MySQL selbst zu beheben.

Die folgenden Schritte haben mein Problem gelöst:

a. Erwägen Sie die folgenden Tabellen und Daten:

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. Jetzt müssen wir einige Zeilen löschen, um das Problem zu demonstrieren:

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

c. PROBLEM: Das Problem tritt auf, wenn Sie versuchen, die folgenden untergeordneten Zeilen einzufügen:

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)

Obwohl die IGNORE Das Schlüsselwort wird verwendet, aber MySQL bricht die angeforderte Operation ab, da der generierte Fehler nicht (wie vorgesehen) in eine Warnung umgewandelt wird. Nun, da das Problem offensichtlich ist, sehen wir uns an, wie wir die letzte insert into-Anweisung ausführen können, ohne auf einen Fehler zu stoßen.

d. LÖSUNG: Ich werde die Insert-in-Anweisung durch einige andere konstante Anweisungen umschließen, die weder von den eingefügten Datensätzen noch von ihrer Anzahl abhängig sind.

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;

Ich weiß, dass dies nicht optimal ist, aber solange MySQL das Problem nicht behoben hat, ist dies das Beste, was ich weiß. Vor allem, da alle Anweisungen in einer Anfrage ausgeführt werden können, wenn Sie die mysqli-Bibliothek in PHP verwenden.