sql >> Databasteknik >  >> RDS >> Mysql

Begränsningar för främmande nyckel:När ska man använda PÅ UPPDATERING och PÅ DELETE

Tveka inte att sätta begränsningar på databasen. Du kommer att vara säker på att ha en konsekvent databas, och det är en av de goda anledningarna att använda en databas. Speciellt om du har flera applikationer som begär det (eller bara en applikation men med ett direktläge och ett batchläge som använder olika källor).

Med MySQL har du inte avancerade begränsningar som du skulle ha i postgreSQL, men åtminstone de främmande nyckelbegränsningarna är ganska avancerade.

Vi tar ett exempel, en företagstabell med en användartabell som innehåller personer från dessa företag

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;

Låt oss titta på PÅ UPPDATERING klausul:

  • PÅ UPPDATERINGSBEGRÄNSNING :standard :om du försöker uppdatera ett företags-id i tabellen COMPANY kommer motorn att avvisa åtgärden om en ANVÄNDARE åtminstone länkar till detta företag.
  • VID UPPDATERING INGEN ÅTGÄRD :samma som RESTRICT.
  • PÅ UPPDATERING CASCADE :den bästa vanligtvis :om du uppdaterar ett företags-id i en rad i tabellen COMPANY kommer motorn att uppdatera det i enlighet med detta på alla USER-rader som refererar till detta FÖRETAG (men inga triggers aktiverade på USER-tabellen, varning). Motorn spårar ändringarna åt dig, det är bra.
  • PÅ UPPDATERING SÄTT NULL :om du uppdaterar ett företags-id i en rad i tabellen COMPANY kommer motorn att ställa in relaterade ANVÄNDARE företags-id till NULL (bör vara tillgängligt i fältet USER företags-id). Jag kan inte se någon intressant sak att göra med det på en uppdatering, men jag kan ha fel.

Och nu på ON DELETE sida:

  • PÅ DELETE BEGRÄNSNING :standard :om du försöker ta bort ett company_id-ID i tabellen COMPANY kommer motorn att avvisa åtgärden om en ANVÄNDARE åtminstone länkar till detta företag, kan rädda ditt liv.
  • PÅ DELETE INGEN ÅTGÄRD :samma som RESTRICT
  • PÅ DELETE CASCADE :farligt :om du tar bort en företagsrad i tabellen FÖRETAG kommer motorn att ta bort även relaterade ANVÄNDARE. Detta är farligt men kan användas för att göra automatiska rensningar på sekundära tabeller (så det kan vara något du vill, men absolut inte för ett FÖRETAG<->ANVÄNDARE exempel)
  • PÅ DELETE SET NULL :handfull :om du tar bort en COMPANY-rad kommer de relaterade ANVÄNDARNA automatiskt att ha relationen till NULL. Om Null är ditt värde för användare utan företag kan detta vara ett bra beteende, till exempel kanske du behöver behålla användarna i din applikation, som författare till visst innehåll, men att ta bort företaget är inget problem för dig.

vanligtvis är min standard:PÅ RADERING BEGRÄNSNING PÅ UPPDATERINGSKASKAD . med någon ON DELETE CASCADE för spårtabeller (loggar--inte alla loggar--, sådana saker) och ON DELETE SET NULL när huvudtabellen är ett 'enkelt attribut' för tabellen som innehåller den främmande nyckeln, som en JOBB-tabell för tabellen USER.

Redigera

Det var länge sedan jag skrev det. Nu tycker jag att jag ska lägga till en viktig varning. MySQL har en stor dokumenterad begränsning med kaskader. Kaskader är inte utlösare . Så om du var tillräckligt säker på den motorn för att använda triggers bör du undvika kaskadbegränsningar.

==> Se nedan den senaste redigeringen, saker rör sig på den här domänen

Och jag tror inte att det här kommer att fixas en dag. Utländska nyckelbegränsningar hanteras av InnoDb-lagringen och triggers hanteras av MySQL SQL-motorn. Båda är separerade. Innodb är den enda lagringen med begränsningshantering, kanske lägger de till triggers direkt i lagringsmotorn en dag, kanske inte.

Men jag har min egen åsikt om vilket element du ska välja mellan den dåliga triggerimplementeringen och det mycket användbara stödet för främmande nycklar. Och när du väl har vant dig vid databaskonsistens kommer du att älska PostgreSQL.

12/2017-Uppdatering av denna redigering om MySQL:

som anges av @IstiaqueAhmed i kommentarerna, har situationen förändrats i detta ämne. Så följ länken och kontrollera den verkliga aktuella situationen (som kan ändras igen i framtiden).



  1. visar länk i php

  2. Jag vill hämta data från olika tabellnamn med postgresql-funktionen

  3. Escape-funktion för reguljära uttryck eller LIKE-mönster

  4. Kan inte ansluta till MySQL-servern på '127.0.0.1' (10061) (2003)