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

Ist es in SQL in Ordnung, wenn zwei Tabellen aufeinander verweisen?

Nein, es ist nicht in Ordnung. Zirkelverweise zwischen Tabellen sind chaotisch. Siehe diesen (zehn Jahre alten) Artikel:SQL By Design:The Circular Reference

Einige DBMS können damit umgehen, und zwar mit besonderer Sorgfalt, aber MySQL wird Probleme haben.

Möglichkeit 1

Als Ihr Design, um einen der beiden FKs nullable zu machen. Damit lösen Sie das Henne-Ei-Problem (in welche Tabelle soll ich zuerst einfügen?).

Es gibt jedoch ein Problem mit Ihrem Code. Dadurch kann ein Produkt ein Standardbild haben, wobei dieses Bild auf ein anderes Produkt verweist!

Um einen solchen Fehler zu verhindern, sollte Ihre FK-Einschränkung wie folgt lauten:

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

Dies erfordert einen UNIQUE Einschränkung/Index in Tabelle products_pictures auf (product_id, id) damit der obige FK definiert ist und richtig funktioniert.

Option 2

Ein anderer Ansatz besteht darin, die Default_Picture_ID zu entfernen Spalte bilden das product Tabelle und fügen Sie ein IsDefault BIT hinzu Spalte im picture Tisch. Das Problem bei dieser Lösung besteht darin, dass nur bei einem Bild pro Produkt dieses Bit aktiviert und bei allen anderen deaktiviert werden kann. In SQL-Server (und ich glaube in Postgres) kann dies mit einem Teilindex erfolgen:

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

Aber MySQL hat keine solche Funktion.

Möglichkeit 3

Mit diesem Ansatz können Sie sogar beide FK-Spalten als NOT NULL definieren ist es, aufschiebbare Einschränkungen zu verwenden. Dies funktioniert in PostgreSQL und ich denke in Oracle. Überprüfen Sie diese Frage und die Antwort von @Erwin:Komplexe Fremdschlüsselbeschränkung in SQLAlchemy (die Alle Schlüsselspalten NICHT NULL Teil).

Beschränkungen in MySQL können nicht verschoben werden.

Option 4

Der Ansatz (den ich am saubersten finde) besteht darin, die Default_Picture_ID zu entfernen Spalte und fügen Sie eine weitere Tabelle hinzu. Kein kreisförmiger Pfad in den FK-Einschränkungen und alle FK-Spalten sind NOT NULL mit dieser Lösung:

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)

Dies erfordert auch einen UNIQUE Einschränkung/Index in Tabelle products_pictures auf (product_id, id) wie in Lösung 1.

Zusammenfassend haben Sie mit MySQL zwei Möglichkeiten:

  • Option 1 (eine Nullable-FK-Spalte) mit der obigen Korrektur, um die Integrität korrekt zu erzwingen

  • Option 4 (keine Nullable-FK-Spalten)