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

Fremmednøglebegrænsninger:Hvornår skal man bruge PÅ OPDATERING og PÅ SLET

Tøv ikke med at sætte begrænsninger på databasen. Du vil være sikker på at have en ensartet database, og det er en af ​​de gode grunde til at bruge en database. Især hvis du har flere applikationer, der anmoder om det (eller kun én applikation, men med en direkte tilstand og en batch-tilstand, der bruger forskellige kilder).

Med MySQL har du ikke avancerede begrænsninger, som du ville have i postgreSQL, men i det mindste er de fremmednøgle begrænsninger ret avancerede.

Vi tager et eksempel, en virksomhedstabel med en brugertabel, der indeholder personer fra afhandlingsvirksomheden

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;

Lad os se på ON UPDATE klausul:

  • PÅ OPDATERINGSBEGRÆNSNING :standarden :hvis du forsøger at opdatere et virksomheds-id i tabellen COMPANY, vil motoren afvise handlingen, hvis mindst én BRUGER linker til denne virksomhed.
  • VED OPDATERING INGEN HANDLING :samme som RESTRICT.
  • PÅ OPDATERING CASCADE :normalt den bedste :hvis du opdaterer et virksomheds-id i en række af tabellen COMPANY, vil motoren opdatere det i overensstemmelse hermed på alle USER-rækker, der refererer til dette COMPANY (men ingen triggere aktiveret på USER-tabellen, advarsel). Motoren vil spore ændringerne for dig, det er godt.
  • ON UPDATE SET NULL :Hvis du opdaterer et virksomheds-id i en række af tabellen COMPANY, vil motoren indstille relaterede BRUGER-virksomheds-id til NULL (skal være tilgængelig i feltet BRUGER virksomheds-id). Jeg kan ikke se nogen interessant ting at gøre med det på en opdatering, men jeg kan tage fejl.

Og nu på ON SLET side:

  • PÅ SLETNINGSBEGRÆNSNING :standarden :hvis du forsøger at slette et company_id-id i tabellen COMPANY, vil motoren afvise handlingen, hvis mindst én BRUGER linker til denne virksomhed, kan redde dit liv.
  • PÅ SLET INGEN HANDLING :samme som RESTRICT
  • PÅ SLET CASCADE :farlig :hvis du sletter en virksomhedsrække i tabellen COMPANY, vil motoren også slette de relaterede BRUGERE. Dette er farligt, men kan bruges til at lave automatiske oprydninger på sekundære tabeller (så det kan være noget, du ønsker, men helt sikkert ikke for et FIRMA<->BRUGER eksempel)
  • PÅ SLET SÆT NULL :håndfuld :hvis du sletter en COMPANY-række, vil de relaterede BRUGERE automatisk have relationen til NULL. Hvis Null er din værdi for brugere uden virksomhed, kan dette være en god adfærd, for eksempel skal du måske beholde brugerne i din applikation, som forfattere af noget indhold, men at fjerne virksomheden er ikke et problem for dig.

normalt er min standard:ON SLET BEGRÆNSNING PÅ OPDATERING CASCADE . med nogle ON DELETE CASCADE for sportabeller (logfiler--ikke alle logfiler--, sådan noget) og ON DELETE SET NULL når mastertabellen er en 'simpel attribut' for tabellen, der indeholder fremmednøglen, som en JOB-tabel for USER-tabellen.

Rediger

Det er længe siden jeg har skrevet det. Nu synes jeg, jeg skal tilføje en vigtig advarsel. MySQL har én stor dokumenteret begrænsning med kaskader. Kaskader er ikke udløsere . Så hvis du var for sikker nok i den motor til at bruge triggere, bør du undgå kaskader-begrænsninger.

==> Se nedenfor den sidste redigering, tingene bevæger sig på dette domæne

Og jeg tror ikke, at det bliver ordnet en dag. Udenlandske nøglebegrænsninger administreres af InnoDb-lageret, og triggere administreres af MySQL SQL-motoren. Begge er adskilt. Innodb er det eneste lager med begrænsningsstyring, måske tilføjer de triggere direkte i lagermotoren en dag, måske ikke.

Men jeg har min egen mening om, hvilket element du skal vælge mellem den dårlige triggerimplementering og den meget nyttige understøttelse af fremmednøgler. Og når du først har vænnet dig til databasekonsistens, vil du elske PostgreSQL.

12/2017-Opdatering af denne redigering om MySQL:

som angivet af @IstiaqueAhmed i kommentarerne, har situationen ændret sig på dette emne. Så følg linket og tjek den reelle up-to-date situation (som kan ændre sig igen i fremtiden).



  1. SQL-kommando ikke afsluttet korrekt?

  2. SQLite aggregerede funktioner

  3. Installer venligst mysql-adapter 'gem install activerecord-mysql-adapter'

  4. Vælg poster fra NU() -1 dag