Mysql
 sql >> Baza danych >  >> RDS >> Mysql

INSERT IGNORE INTO w MySQL i klucze obce

[NOWA ODPOWIEDŹ]

Dziękuję @NeverEndingQueue za poruszenie tego tematu. Wygląda na to, że MySQL w końcu rozwiązał ten problem. Nie jestem pewien, w której wersji ten problem został rozwiązany po raz pierwszy, ale teraz testowałem z następującą wersją i problem już nie istnieje:

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

Aby było jasne:

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

Aby lepiej zrozumieć znaczenie tego ostatniego zapytania i dlaczego pokazuje ono, że problem został rozwiązany, przejdź do starej odpowiedzi poniżej.

[STARA ODPOWIEDŹ]

Moje rozwiązanie to obejście problemu, a rzeczywistym rozwiązaniem zawsze będzie naprawienie problemu w samym MySQL.

Następujące kroki rozwiązały mój problem:

a. Rozważ posiadanie następujących tabel i danych:

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. Teraz musimy usunąć niektóre wiersze, aby zademonstrować problem:

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

c. PROBLEM: Problem pojawia się, gdy próbujesz wstawić następujące wiersze podrzędne:

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)

Mimo że IGNORE słowo kluczowe jest używane, ale MySQL anuluje żądaną operację, ponieważ wygenerowany błąd nie jest zamieniany w ostrzeżenie (tak jak powinien). Teraz, gdy problem jest oczywisty, zobaczmy, jak możemy wykonać ostatnią instrukcję wstawiania do instrukcji bez napotkania błędu.

d. ROZWIĄZANIE: Zamierzam zawinąć wstawkę do instrukcji przez inne stałe instrukcje, które nie są ani zależne od wstawionych rekordów, ani od ich liczby.

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;

Wiem, że to nie jest optymalne, ale dopóki MySQL nie naprawi problemu, to jest to najlepsze, co znam. Zwłaszcza, że ​​wszystkie instrukcje mogą być wykonane w jednym żądaniu, jeśli używasz biblioteki mysqli w PHP.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Użyj rozszerzeń przestrzennych MySQL, aby wybrać punkty wewnątrz okręgu

  2. PHP Mysql łączy się w różnych bazach danych

  3. mysql kolejność według liczby wydajności

  4. Uzyskaj różnicę lat między dwiema datami w MySQL jako liczbę całkowitą

  5. Przechowywać pliki obrazów lub adresy URL w bazie danych MySQL? Co jest lepsze?