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

I SQL, er det OK for to tabeller at referere til hinanden?

Nej, det er ikke i orden. Cirkulære referencer mellem tabeller er rodet. Se denne (årti gamle) artikel:SQL By Design:The Circular Reference

Nogle DBMS kan håndtere disse, og med særlig omhu, men MySQL vil have problemer.

Mulighed 1

Som dit design, at gøre en af ​​de to FK'er nullbar. Dette giver dig mulighed for at løse kylling-og-æg-problemet (hvilken tabel skal jeg først indsætte i?).

Der er dog et problem med din kode. Det vil tillade et produkt at have et standardbillede, hvor billedet vil referere til et andet produkt!

For at afvise en sådan fejl skal din FK-begrænsning være:

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

Dette kræver en UNIQUE constraint/index i tabel products_pictures(product_id, id) for at ovenstående FK defineres og fungerer korrekt.

Mulighed 2

En anden fremgangsmåde er at fjerne Default_Picture_ID kolonne fra product tabel og tilføj en IsDefault BIT kolonne i picture bord. Problemet med denne løsning er, hvordan man kun tillader et billede pr. produkt at have den bit på og alle andre at have det slukket. I SQL-Server (og jeg tror i Postgres) kan dette gøres med et delvist indeks:

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

Men MySQL har ingen sådan funktion.

Mulighed 3

Denne tilgang tillader dig endda at have begge FK-kolonner defineret som NOT NULL er at bruge udskydbare begrænsninger. Dette virker i PostgreSQL, og jeg tror i Oracle. Tjek dette spørgsmål og svaret af @Erwin:Kompleks fremmednøglebegrænsning i SQLAlchemy (Alle nøglekolonner IKKE NULL del).

Begrænsninger i MySQL kan ikke udskydes.

Mulighed 4

Fremgangsmåden (som jeg finder den reneste) er at fjerne Default_Picture_ID kolonne og tilføje endnu en tabel. Ingen cirkulær sti i FK-begrænsningerne, og alle FK-kolonner vil være NOT NULL med denne løsning:

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)

Dette kræver også en UNIQUE constraint/index i tabel products_pictures(product_id, id) som i løsning 1.

For at opsummere, med MySQL har du to muligheder:

  • mulighed 1 (en nullbar FK-kolonne) med rettelsen ovenfor for at håndhæve integriteten korrekt

  • mulighed 4 (ingen nullbare FK-kolonner)



  1. Hvorfor bruge Vælg Top 100 procent?

  2. Forhistorisk og moderne tilgang til designdatabaser

  3. hvordan får man vist fuld lagret procedurekode?

  4. Forståelse af Always ON Availability Group mellem Linux-baserede SQL Server-instanser. Del 1