sql >> Database >  >> RDS >> Mysql

Is het in SQL OK dat twee tabellen naar elkaar verwijzen?

Nee, het is niet oke. Cirkelverwijzingen tussen tabellen zijn rommelig. Zie dit (tien jaar oud) artikel:SQL By Design:The Circular Reference

Sommige DBMS kunnen hiermee omgaan, en met speciale zorg, maar MySQL zal problemen hebben.

Optie 1

Als jouw ontwerp, om een ​​van de twee FK's nullable te maken. Hiermee kun je het kip-en-ei-probleem oplossen (in welke tabel moet ik het eerst invoegen?).

Er is echter een probleem met uw code. Hierdoor kan een product een standaardafbeelding hebben waar die afbeelding naar een ander product verwijst!

Om een ​​dergelijke fout niet toe te staan, moet uw FK-beperking zijn:

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

Dit vereist een UNIQUE beperking/index in tabel products_pictures op (product_id, id) om de bovenstaande FK te definiëren en correct te laten werken.

Optie 2

Een andere benadering is het verwijderen van de Default_Picture_ID kolom uit het product tabel en voeg een IsDefault BIT toe kolom in de picture tafel. Het probleem met deze oplossing is hoe je slechts één foto per product toestaat om dat bit aan te hebben en alle anderen om het uit te hebben. In SQL-Server (en ik denk in Postgres) kan dit met een gedeeltelijke index:

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

Maar MySQL heeft zo'n functie niet.

Optie 3

Met deze aanpak kunt u zelfs beide FK-kolommen definiëren als NOT NULL is om uitstelbare beperkingen te gebruiken. Dit werkt in PostgreSQL en ik denk in Oracle. Controleer deze vraag en het antwoord van @Erwin:Complexe externe sleutelbeperking in SQLAlchemy (de Alle sleutelkolommen NIET NULL deel).

Beperkingen in MySQL kunnen niet worden uitgesteld.

Optie 4

De aanpak (die ik het schoonst vind) is om de Default_Picture_ID . te verwijderen kolom en voeg nog een tabel toe. Geen cirkelvormig pad in de FK-beperkingen en alle FK-kolommen zijn NOT NULL met deze oplossing:

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)

Dit vereist ook een UNIQUE beperking/index in tabel products_pictures op (product_id, id) zoals in oplossing 1.

Om samen te vatten, met MySQL heb je twee opties:

  • optie 1 (een nullable FK-kolom) met de bovenstaande correctie om integriteit correct af te dwingen

  • optie 4 (geen nullable FK-kolommen)



  1. bereken een som van typetijd met behulp van sql

  2. Virtuele machine verwijderen uit VirtualBox

  3. Laatste index van een string vinden in Oracle

  4. Mysql-dumps en -importen versnellen