sql >> Database >  >> RDS >> Mysql

Beperkingen voor externe sleutels:wanneer moet u ON UPDATE en ON DELETE gebruiken?

Aarzel niet om beperkingen op te leggen aan de database. U bent zeker van een consistente database en dat is een van de goede redenen om een ​​database te gebruiken. Vooral als je meerdere applicaties hebt die erom vragen (of slechts één applicatie maar met een directe modus en een batchmodus die verschillende bronnen gebruikt).

Met MySQL heb je geen geavanceerde beperkingen zoals je zou hebben in postgreSQL, maar de externe sleutelbeperkingen zijn in ieder geval behoorlijk geavanceerd.

We nemen een voorbeeld, een bedrijfstabel met een gebruikerstabel met mensen van dit bedrijf

CREATE TABLE COMPANY (
     company_id INT NOT NULL,
     company_name VARCHAR(50),
     PRIMARY KEY (company_id)
) ENGINE=INNODB;

CREATE TABLE USER (
     user_id INT, 
     user_name VARCHAR(50), 
     company_id INT,
     INDEX company_id_idx (company_id),
     FOREIGN KEY (company_id) REFERENCES COMPANY (company_id) ON...
) ENGINE=INNODB;

Laten we eens kijken naar de ON UPDATE clausule:

  • BEPERK BIJ UPDATE :de standaard :als u een company_id in tabel COMPANY probeert bij te werken, zal de engine de bewerking weigeren als één GEBRUIKER op zijn minst naar dit bedrijf linkt.
  • BIJ UPDATE GEEN ACTIE :hetzelfde als BEPERKEN.
  • OP UPDATE CASCADE :meestal de beste :als u een company_id in een rij van tabel COMPANY bijwerkt, zal de engine het dienovereenkomstig bijwerken op alle USER-rijen die verwijzen naar dit COMPANY (maar er zijn geen triggers geactiveerd op de USER-tabel, waarschuwing). De engine houdt de wijzigingen voor je bij, dat is goed.
  • OP UPDATE NULL INSTELLEN :als u een bedrijfs-id in een rij van tabel BEDRIJF bijwerkt, stelt de engine de gerelateerde USER-bedrijfs-id in op NULL (moet beschikbaar zijn in het veld USER company_id). Ik kan daar niets interessants mee zien in een update, maar ik kan het mis hebben.

En nu op de ON DELETE kant:

  • OP VERWIJDEREN BEPERKEN :de standaard :als u een company_id Id in tabel COMPANY probeert te verwijderen, zal de engine de bewerking afwijzen als één GEBRUIKER op zijn minst naar dit bedrijf linkt, uw leven kan redden.
  • OP VERWIJDEREN GEEN ACTIE :hetzelfde als BEPERKEN
  • OP VERWIJDEREN CASCADE :gevaarlijk :als u een bedrijfsrij in tabel BEDRIJF verwijdert, verwijdert de engine ook de gerelateerde GEBRUIKERS. Dit is gevaarlijk, maar kan worden gebruikt om automatische opschoningen uit te voeren op secundaire tabellen (dus het kan iets zijn dat u wilt, maar zeker niet voor een BEDRIJF<->GEBRUIKER-voorbeeld)
  • OP VERWIJDEREN NULL INSTELLEN :handvol :als u een COMPANY-rij verwijdert, hebben de gerelateerde GEBRUIKERS automatisch de relatie met NULL. Als Null uw waarde is voor gebruikers zonder bedrijf, kan dit een goed gedrag zijn, u moet bijvoorbeeld de gebruikers in uw toepassing houden als auteurs van bepaalde inhoud, maar het verwijderen van het bedrijf is geen probleem voor u.

meestal is mijn standaard:OP VERWIJDEREN BEPERKEN OP UPDATE CASCADE . met wat ON DELETE CASCADE voor tracktabellen (logs--niet alle logs--, dat soort dingen) en ON DELETE SET NULL wanneer de hoofdtabel een 'eenvoudig attribuut' is voor de tabel die de refererende sleutel bevat, zoals een JOB-tabel voor de USER-tabel.

Bewerken

Het is lang geleden dat ik dat heb geschreven. Nu denk ik dat ik een belangrijke waarschuwing moet toevoegen. MySQL heeft één grote gedocumenteerde beperking met cascades. Cascades activeren geen triggers . Dus als je genoeg vertrouwen had in die engine om triggers te gebruiken, zou je cascadebeperkingen moeten vermijden.

==> Zie onder de laatste bewerking, dingen bewegen op dit domein

En ik denk niet dat dit op een dag zal worden opgelost. Foreign key-beperkingen worden beheerd door de InnoDb-opslag en triggers worden beheerd door de MySQL SQL-engine. Beide zijn gescheiden. Innodb is de enige opslag met beperkingsbeheer, misschien zullen ze ooit triggers rechtstreeks in de opslagengine toevoegen, misschien niet.

Maar ik heb mijn eigen mening over welk element je moet kiezen tussen de slechte trigger-implementatie en de zeer nuttige ondersteuning voor externe sleutels. En als u eenmaal gewend bent aan databaseconsistentie, zult u dol zijn op PostgreSQL.

12/2017-Deze bewerking over MySQL bijwerken:

zoals vermeld door @IstiaqueAhmed in de opmerkingen, is de situatie op dit gebied veranderd. Dus volg de link en bekijk de echte actuele situatie (die in de toekomst weer kan veranderen).



  1. Inleiding tot Storage Spaces Direct voor SQL Server

  2. Hoe kan ik transparante gegevensversleuteling gebruiken met MySQL?

  3. SQL Server FOR XML Pad maken herhalende knooppunten

  4. MySQL-connectorfout De waarde van de servertijdzone Midden-Europese tijd