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

Czy w SQL można odwoływać się do siebie w dwóch tabelach?

Nie, nie jest ok. Okrągłe odniesienia między tabelami są bałaganiarskie. Zobacz ten (dziesięcioletni) artykuł:SQL By Design:The Circular Reference

Niektóre DBMS mogą sobie z tym poradzić i to ze szczególną ostrożnością, ale MySQL będzie miał problemy.

Opcja 1

Jako twój projekt, aby jeden z dwóch FK był nieważny. To pozwala rozwiązać problem z kurczakiem i jajkiem (do której tabeli powinienem najpierw wstawić?).

Jest jednak problem z twoim kodem. Dzięki temu produkt będzie miał domyślne zdjęcie, w którym to zdjęcie będzie odnosić się do innego produktu!

Aby uniemożliwić taki błąd, twoje ograniczenie FK powinno być:

CONSTRAINT FK_products_1 
  FOREIGN KEY (id, default_picture_id) 
  REFERENCES products_pictures (product_id, id)
  ON DELETE RESTRICT                            --- the SET NULL options would 
  ON UPDATE RESTRICT                            --- lead to other issues

Będzie to wymagało UNIQUE ograniczenie/indeks w tabeli products_pictures na (product_id, id) aby powyższe FK było zdefiniowane i działało poprawnie.

Opcja 2

Innym podejściem jest usunięcie Default_Picture_ID kolumna z product tabeli i dodaj IsDefault BIT kolumna w picture stół. Problem z tym rozwiązaniem polega na tym, aby tylko jedno zdjęcie na produkt miało ten bit, a wszystkie inne go miały. W SQL-Server (a myślę, że w Postgresie) można to zrobić za pomocą częściowego indeksu:

CREATE UNIQUE INDEX is_DefaultPicture 
  ON products_pictures (Product_ID)
  WHERE IsDefault = 1 ;

Ale MySQL nie ma takiej funkcji.

Opcja 3

Takie podejście pozwala nawet mieć obie kolumny FK zdefiniowane jako NOT NULL jest użycie odroczonych ograniczeń. Działa to w PostgreSQL i myślę, że w Oracle. Sprawdź to pytanie i odpowiedź @Erwin:Złożone ograniczenie klucza obcego w SQLAlchemy (Wszystkie kluczowe kolumny NOT NULL Część).

Ograniczeń w MySQL nie można odroczyć.

Opcja 4

Podejście (które uważam za najczystsze) polega na usunięciu Default_Picture_ID kolumnę i dodaj kolejną tabelę. Brak ścieżki kołowej w ograniczeniach FK i wszystkie kolumny FK będą NOT NULL z tym rozwiązaniem:

product_default_picture
----------------------
product_id          NOT NULL
default_picture_id  NOT NULL
PRIMARY KEY (product_id)
FOREIGN KEY (product_id, default_picture_id)
  REFERENCES products_pictures (product_id, id)

Będzie to również wymagało UNIQUE ograniczenie/indeks w tabeli products_pictures na (product_id, id) jak w rozwiązaniu 1.

Podsumowując, w MySQL masz dwie opcje:

  • opcja 1 (kolumna FK dopuszczająca wartość null) z powyższą poprawką w celu poprawnego wymuszenia integralności

  • opcja 4 (bez pustych kolumn FK)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Wprowadzenie do grupowania i sumowania SQL

  2. MySQL tworzy składnię procedury składowanej z ogranicznikiem

  3. Jak działa funkcja LPAD() w MySQL

  4. Kompleksowy przewodnik dotyczący korzystania z MySQL

  5. Przewodnik po zrozumieniu wzorców skalowania bazy danych