sql >> Database teknologi >  >> RDS >> Mysql

MySQL's INSERT IGNORE INTO &fremmednøgler

[NYT SVAR]

Tak til @NeverEndingQueue for at bringe dette op. Det ser ud til, at MySQL endelig har løst dette problem. Jeg er ikke sikker på, hvilken version dette problem først blev rettet i, men lige nu testede jeg med følgende version, og problemet er der ikke længere:

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

For at være klar:

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

For bedre at forstå betydningen af ​​denne sidste forespørgsel, og hvorfor den viser, at problemet er løst, skal du fortsætte med det gamle svar nedenfor.

[GAMMEL SVAR]

Min løsning er en løsning på problemet, og den faktiske løsning vil altid være at løse problemet i selve MySQL.

Følgende trin løste mit problem:

a. Overvej at have følgende tabeller og 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 skal vi slette nogle af rækkerne for at demonstrere problemet:

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

c. PROBLEM: Problemet opstår, når du forsøger at indsætte følgende underordnede rækker:

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)

Selvom IGNORE nøgleordet bruges, men MySQL annullerer den anmodede handling, fordi den genererede fejl ikke omdannes til advarsel (som den skulle). Nu hvor problemet er åbenlyst, lad os se, hvordan vi kan udføre den sidste indsættelse i sætning uden at se nogen fejl.

d. LØSNING: Jeg vil pakke indsættet ind i et udsagn med nogle andre konstante udsagn, som hverken er afhængige af de indsatte poster eller deres 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;

Jeg ved, at dette ikke er optimalt, men så længe MySQL ikke har løst problemet, er dette det bedste, jeg ved. Især da alle sætningerne kan udføres i én anmodning, hvis du bruger mysqli-biblioteket i PHP.



  1. Sådan tilføjer du standardbegrænsning til eksisterende kolonner i SQL Server-tabel - SQL Server / TSQL selvstudium, del 91

  2. MySQL:Adgang nægtet for brugeren 'test'@'localhost' (ved hjælp af adgangskode:JA) undtagen root-bruger

  3. mysql-kommando til at vise aktuelle konfigurationsvariabler

  4. PGEast, Hardware Benchmarking og PG Performance Farm