sql >> Databasteknik >  >> RDS >> Mysql

Primärnyckel SQL-handledning – Hur man definierar en primärnyckel i en databas

Varje stor historia börjar med en identitetskris. Luke, den store Jedimästaren, börjar osäker - "Vem är jag?" - och hur skulle jag kunna vara någon viktig? Det krävs Yoda, den som har Kraften, för att lära honom hur man utnyttjar sina krafter.

Idag, låt mig vara din Yoda.

Vi börjar med hur man väljer en primärnyckel, bekämpar en identitetskris och avslutar sedan med kodexempel för att skapa en primärnyckel i en databas.

Hur man väljer en primär nyckel

Du kanske tror att Luke är den ende med en identitetskris, men det är inte sant. När man skapar en databas är allt i en identitetskris. Och det är precis därför vi behöver primärnycklar:de löser krisen. De berättar för oss hur vi hittar alla.

Föreställ dig att du är regeringen och att du vill identifiera var och en av dina medborgare digitalt. Så du skapar den här databasen med allt om dem:

First Name
Last Name
Passport Number

Du väljer passnumret som Primärnyckel - identiteten för alla. Du tror att det är allt du behöver eftersom passet har adressen och allt annat. Du vet att passnummer är unika, så du mår bra och implementerar det här systemet.

Sedan, några år senare, får du reda på en ful sanning:hela landet står inför en identitetskris.

När någons pass går ut får de ett nytt. Deras identitet förändras. Andra system fortsätter att använda de gamla passnumren, så de pekar nu på spökfolk.

Unikitet räcker inte. Värdet får inte ändras under radens livstid.

Och sedan upptäcker du att det finns några människor som inte ens har pass. Du kan inte ange dem i ditt system, eftersom primärnycklar inte kan vara NULL . Hur kan du identifiera någon med en NULL nyckel?

Varje rad måste ha en identifierare. NULLs inte tillåtna.

Nästa iteration innebär att hitta en identifierare som inte förändras över tiden, och en som alla har. I Indien visar sig detta vara Adhaar-kortet. I USA, personnummer.

Om du skapar en databas, gör dessa till dina primära nycklar.

Ibland har du ingen sådan nyckel. Tänk på ett land som inte har ett personnummer ännu, och de vill skapa ett digitalt register över alla medborgare. De kan skapa ett nytt SSN, eller så kan de bara utnyttja kraften i databaser och använda en surrogatnyckel.

En surrogatnyckel har ingen motsvarighet i den verkliga världen. Det är bara ett nummer i en databas. Så du har den här tabellen i det nya landet:

userID
First Name
Last Name
Passport Number

Passnummer är unika. Närhelst du vill få identifieraren för en användare kan du få den via passnumret.

Användar-ID ändras aldrig. Passnumret kan ändras – men det är alltid unikt, så du får alltid rätt användare. Användar-ID är ett surrogat för ett icke-existerande personnummer i detta land.

Roligt faktum:Passnumret här är också en kandidatnyckel. Det kunde ha varit den primära nyckeln, om den aldrig förändrats. Detta är en distinktion av affärslogik.

Det viktigaste är detta:När du väljer en primärnyckel, tänk på en identitetskris . Är det möjligt att någon ändrar sin identifierare i framtiden? Kan vi hamna i ett tillstånd där flera personer har samma identifierare?

Jag använder människor som exempel, eftersom det gör identiteten tydligare - vi vet att varje person ska ha en identitet. Överför detta tänkande till dina databaser. Allt har en identitet, det är precis därför du behöver primärnycklar.

Obs:Ibland är det möjligt och önskvärt att använda flera kolumner tillsammans som den primära nyckeln. Detta är en sammansatt nyckel.

Låt oss nu försöka definiera primärnycklar med riktiga kodexempel. Det finns två saker att göra här:först ska du identifiera den primära nyckeln. Sedan lär du dig syntaxen för att definiera den i en databas.

Ett exempel från verkligheten

Låt oss säga att du driver en fraktstart, ungefär som Flexport. Du har paket som måste ta sig från en plats till en annan, och fartyg som transporterar dem. Dessutom har du kunder som beställer dessa paket.

Du tror att du behöver ett bord för kunderna, ett för paketen och ett för transport, som visar vilket paket som är var just nu.

Fundera igenom vilka kolumner du behöver och vad som bör vara den primära nyckeln. Om du var ingenjör på Flexport, är detta en faktisk fråga du skulle behöva ta reda på. Ingenting är givet, allt upptäcks i den verkliga världen.

Med den här informationen skulle jag designa dessa tabeller så här:

Customers: first_name, last_name, email, address (for deliveries to their location)
Packages: weight, content
Transportation: <package_primary_key>, Port, time

Vi saknar primärnycklarna. Tänk på dem innan du läser vidare.

För paketet väljer jag ett surrogat Paket-ID. Jag kunde ha försökt lista alla attribut för förpackningen:vikt, volym, densitet, ålder. De skulle identifiera paketet unikt, men detta är mycket svårt att göra i praktiken. Människor bryr sig inte om detta, de bryr sig bara om att paketet kommer från en plats till en annan.

Så det är vettigt att skapa ett slumpmässigt nummer och använda det som ID. Det är precis därför du ser att FedEx, UPS och alla leveranstjänster använder streckkoder och ID:n. Dessa är surrogatnycklar som genereras för att spåra paket.

För kunden väljer jag ett surrogat Kundnummer. Här, återigen, hade jag ett alternativ att välja, säg, personnummer för mina kunder. Men kunder vill inte dela detta med mig bara så att jag kan skicka något till dem. Därför genererar vi en nyckel internt, berättar inte för våra kunder om denna nyckel, och fortsätter att kalla dem CustomerNo. 345681.

Rolig historia:Jag känner några företag där de avslöjade detta kundnummer, och kunderna insisterade på att de skulle få nr 1. Det var ganska roligt - ingenjörerna var faktiskt tvungna att ändra sin front-end-kod till:if (cust == 345681) print(1);

För transport väljer jag en komposit PackageID+Port+tid. Det här är lite mer intressant. Jag kunde ha skapat ett surrogat här också, och det skulle fungera lika bra.

Men här ligger magin med indexering. De primära nycklarna får ett index automatiskt, vilket innebär att sökning är mycket effektivare än primärnycklar.

När du söker igenom den här databasen kommer de flesta frågorna att ha formen "var är det här paketet?". Med andra ord, givet detta paket-ID, berätta för mig vilken port och tid det är just nu. Jag skulle behöva ett extra index över PackageID om jag inte har det som en del av min primära nyckel.

Låter detta bra? Sista steget, låt oss definiera dessa tre tabeller i SQL. Syntaxen varierar något med den databas du använder.

Definiera primärnycklar i MySQL

CREATE TABLE customers
( customerID  INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  last_name   VARCHAR(30) NOT NULL,
  first_name  VARCHAR(25) NOT NULL,
  email		  VARCHAR(50) NOT NULL,
  address     VARCHAR(300)
);
CREATE TABLE packages
( packageID  INT(15) NOT NULL AUTO_INCREMENT,
  weight     DECIMAL (10, 2) NOT NULL,
  content    VARCHAR(50),
  CONSTRAINT packages_pk PRIMARY KEY (packageID) # An alternative way to above,
  # when you want to name the constraint as well.
);
CREATE TABLE transportation
( package 	INT(15) NOT NULL,
  port  	INT(15) NOT NULL,
  time	 	DATE NOT NULL,
  
  PRIMARY KEY (package, port, time),
  FOREIGN KEY package
  	REFERENCES packages(packageID)
	ON DELETE RESTRICT    # It's good practice to define what should happen on deletion. In this case, I don't want things to get deleted.

);

Definiera primärnycklar i PostgreSQL

CREATE TABLE customers
( customerID  SERIAL NOT NULL PRIMARY KEY, # In PostgreSQL SERIAL is same as AUTO_INCREMENT - it adds 1 to every new row.
  last_name   VARCHAR(30) NOT NULL,
  first_name  VARCHAR(25) NOT NULL,
  address     TEXT,
  email		  VARCHAR(50) NOT NULL
);
CREATE TABLE packages
( packageID  SERIAL NOT NULL,
  weight     NUMERIC NOT NULL,
  content    TEXT,
  CONSTRAINT packages_pk PRIMARY KEY (packageID) # In PostgreSQL, this alternative way works too.
);
CREATE TABLE transportation
( package 	INTEGER NOT NULL,
  port  	INT(15) NOT NULL,
  time	 	DATE NOT NULL,
  
  PRIMARY KEY (package, port, time),
  
  FOREIGN KEY package
  	REFERENCES packages(packageID)
	ON DELETE RESTRICT    # It's good practice to define what should happen on deletion. In this case, I don't want things to get deleted.

);

Det är väl inte särskilt annorlunda? När du väl har förstått grunderna kan du tillämpa den på nästan vilken databas som helst med bara en snabb titt i dokumentationen. Nyckeln är att veta vad man ska leta efter!

Lycka till, unge padawan.

Gillade detta? Du kanske också gillar Things I Learned From a Senior Software Engineer



  1. Hur hittar man aktuell transaktionsnivå?

  2. Konvertera MySQL till SQLite

  3. MySQL DATEDIFF() vs TIMESTAMPDIFF():Vad är skillnaden?

  4. SQL Server sp_msforeachtable användning för att välja endast de tabeller som uppfyller något villkor