sql >> Databasteknik >  >> RDS >> Mysql

MySQL främmande nycklar

Främmande nycklar är en integrerad del av att skapa en relation i relationsdatabaser. Här är varför och hur du skapar dem.

Så vi har fastställt att en primärnyckel ger en unik identifierare för tabellen. Men primärnycklar är inte den enda "nyckel"-typen. Vår databas kan också innehålla främmande nycklar.

Vad är en främmande nyckel?

En främmande nyckel är en kolumn (eller samling kolumner) i en tabell som unikt identifierar en rad i en annan tabell. Detta definierar en relation mellan de två tabellerna.

Med en främmande nyckel kan du korsreferens relaterad data över tabeller. Detta är praktiskt när en kolumn innehåller data som är representerade i en annan tabell.

Exempel

Här är ett diagram över vår FruitShop databas som visar förhållandet mellan Fruit tabellen och Enheter tabell.

Den svarta linjen som länkar samman de två tabellerna indikerar en främmande nyckel. UnitId fältet på Fruit tabellen är en främmande nyckel till UnitId fältet på Enheter tabell. Därför värdet som vi infogar i Fruit.UnitId måste motsvara ett värde i Units.UnitId . Detta aktiverar Fruit.UnitId för att referera till data i de andra kolumnerna för den posten (dvs. posten som har motsvarande UnitId ).

Datan

Så om vår Fruit tabellen innehåller en post som denna:

FruitId FruitName Inventering UnitId Inmatat datum Uppdaterad datum
1 Apple 10 3 2012-11-27 12:42:10 2012-11-27 12:42:10

Och våra Enheter tabellen innehåller följande poster:

UnitId Enhetsnamn Inmatat datum Uppdaterad datum
1 Stycke 2011-12-30 12:46:15 2011-12-30 12:46:15
2 Gäng 2011-12-30 12:46:15 2011-12-30 12:46:15
3 Kilogram 2011-12-30 12:46:15 2011-12-30 12:46:15
4 Behållare 2011-12-30 12:46:15 2011-12-30 12:46:15
5 Pund 2011-12-30 12:46:15 2011-12-30 12:46:15
6 Us 2011-12-30 12:46:15 2011-12-30 12:46:15

Du kan se att Fruit.UnitId fältet innehåller en 3 . Titta nu på Enheter tabell för posten som innehåller en 3 i UnitId fält. Du kan se att denna post representerar kilogram . Därför vet vi nu att äpplen mäts i kilogram.

Det som är bra med att ställa in databasen på det här sättet är att vi inte behöver upprepa "kilogram" för varje post som använder den enheten. Att minska dubbelarbete är en viktig fördel med relationsdatabashanteringssystem.

Se lika många poster i Fruit tabell kommer att dela samma enhetsnamn (t.ex. "Kilogram", "Container", "Bunch", etc), bör vi tänka noga innan vi lägger till dubbletter i vår databas. Utan att använda en främmande nyckelrelation skulle vi bara kunna skriva enhetsnamnen rakt in i Fruit tabell (och kanske kalla kolumnen "Unit", "UnitType" eller "UnitName"). Då skulle vi få många poster som delar samma värde för enhetsnamnkolumnen. Vi skulle se "Kilogram" upprepas om och om igen mot många skivor. Vi skulle också se "Bunch" upprepas, och någon annan populär enhetstyp.

Även om det inte nödvändigtvis är "fel" att göra detta, är det i allmänhet mer effektivt att lagra en post för varje enhetsnamn i en separat tabell och sedan referera till den tabellen via UnitId kolumn. Att göra detta är mer effektivt än att upprepa dessa enhetsnamn om och om igen för varje post som skapas i Fruits tabell. Det gör det också lättare om vi någon gång bestämmer oss för att uppdatera ett enhetsnamn (byt till exempel "Kilogram" till "Kilos"). Om vi ​​uppdaterar ett enhetsnamn skulle det inte påverka Fruit tabell eftersom UnitId kommer att förbli densamma. Dessutom hjälper det också till att förhindra att inkonsekvent data dyker upp i vår databas.

Begränsning för främmande nyckel

En främmande nyckel-begränsning är ett databasobjekt som hjälper till att hålla dina främmande nyckeldata konsekventa. Du skapar en främmande nyckel-begränsning för att upprätthålla referensintegritet. Genom att skapa en främmande nyckel-begränsning säger du till MySQL att upprätthålla vissa regler över data. När data infogas, raderas eller uppdateras kommer MySQL att kontrollera att den följer den främmande nyckeln som du skapade mellan tabeller. Om inte, kommer det att förhindra att data skrivs/skrivs över/raderas, vilket bibehåller referensintegriteten.

Till exempel, om en användare försöker ange ett UnitId-värde i Fruit.UnitId kolumnen men det finns ingen motsvarande post i Units.UnitId kolumnen, kommer MySQL att hindra användaren från att ange det värdet.

När vi skapade våra två tabeller lade vi till en främmande nyckel-begränsning till Fruit tabell. Här är koden vi använde för att skapa begränsningen:

CONSTRAINT fkFruitUnits FOREIGN KEY (UnitId) REFERENCES Units (UnitId) ON DELETE RESTRICT ON UPDATE CASCADE

När du expanderar noderna i den vänstra SCHEMAS fliken, kan du se den främmande nyckeln vi skapade (liksom primärnycklarna):

Om du försöker infoga data som inte överensstämmer med begränsningen för främmande nyckel bör du få ett felmeddelande.

Till exempel, om jag försöker infoga en post i Fruit tabell med ett UnitId värde som inte finns i Enheter tabell får jag följande felmeddelande:

Detta beror på att jag försöker infoga värdet 5 till UnitId kolumnen när det inte finns något motsvarande värde i Units.UnitId fältet.

För att detta ska lyckas måste jag se till att det finns ett rekord i Enheter tabell med ett UnitId av 5 .

Utländsk nyckel fungerar inte?

Du kan stöta på en situation då en främmande nyckel inte verkar fungera. Du kan till exempel infoga data i en tabell även om det finns en främmande nyckel som ska förhindra att data infogas.

Det finns några saker du kan kontrollera i den här situationen.

  • Se till att du har lagt till ON DELETE och ON UPDATE klausuler i din kod. Till exempel, ON DELETE RESTRICT ON UPDATE CASCADE . Se vårt CREATE TABLE-exempel för när du ska placera den här koden.
  • Se till att tabellen är InnoDB . Du kan göra detta genom att lägga till ENGINE=InnoDB till slutet av din CREATE TABLE uttalande (se mitt exempel från när vi skapade våra tabeller). Vissa motorer (som MyISAM ) stöder inte begränsningar för främmande nyckel, men de ger ingen varning om detta när du försöker skapa din främmande nyckel begränsning. Om din standardmotor inte är InnoDB då är det troligt att dina främmande nycklar inte stöds.
  • Se till att MySQL faktiskt kontrollerar främmande nycklar. Du kan göra detta genom att köra följande kod:SET FOREIGN_KEY_CHECKS=1 .

Inaktivera kontroll av främmande nycklar

Det kan finnas tillfällen då begränsningar för främmande nyckel kan bli onödigt restriktiva - till den grad att de allvarligt hindrar dina ansträngningar att ladda data. Till exempel, när du precis har skapat en databas och du behöver ladda den första datan. Eller om du behöver släppa ett gäng tabeller och ladda om data.

Om du inte laddar data i rätt ordning kommer du förmodligen att fortsätta få fel med främmande nyckel på grund av att data laddas i fel ordning (dvs. du försöker ladda de underordnade tabellerna innan de överordnade tabellerna har fått sina data laddade).

Det här är inte bara ett problem vid lastning uppgifterna. Du kan också stöta på detta problem när du skapar databasen i första hand. Om du inte skapar tabellerna i rätt ordning kan du stöta på fel på grund av eventuella främmande nyckelbegränsningar.

Om du inte känner till rätt förälder-barn-ordning kan det möjligen ta mycket tid och ansträngning att fastställa rätt ordning för att skapa databasen eller ladda data. I sådana här fall kan det vara bättre att säga åt MySQL tillfälligt att inte kontrollera främmande nycklar för tillfället.

Du kan inaktivera kontroll av främmande nyckel med följande kod:

FOREIGN_KEY_CHECKS=0

För att aktivera det igen, gör så här:

FOREIGN_KEY_CHECKS=1

  1. Hur man bäst delar csv-strängar i oracle 9i

  2. SQL Server 2016:sys.dm_exec_function_stats

  3. "VARNING:Felmatchning hittades mellan sl_table och pg_class." i Slony-I

  4. 3 sätt att returnera en lista över SQL Server Agent-jobb (T-SQL)