Každý velký příběh začíná krizí identity. Luke, velký mistr Jedi, začíná nejistě – "Kdo jsem?" - a jak bych mohl být někdo důležitý? Je zapotřebí Yoda, ten se Sílou, aby ho naučil, jak využít své síly.
Dnes mě dovolte být vaším Yodou.
Začneme tím, jak vybrat primární klíč, jak bojovat s krizí identity, a poté skončíme ukázkami kódu pro vytvoření primárního klíče v databázi.
Jak vybrat primární klíč
Možná si myslíte, že Luke je jediný, kdo má krizi identity, ale není to pravda. Při vytváření databáze je vše v krizi identity. A to je přesně důvod, proč potřebujeme primární klíče:řeší krizi. Říkají nám, jak každého najít.
Představte si, že jste vláda a chcete digitálně identifikovat každého ze svých občanů. Vytvoříte tedy tuto databázi se vším o nich:
First Name
Last Name
Passport Number
Jako primární klíč si zvolíte číslo pasu – identitu pro každého. Uvědomíte si, že to je vše, co potřebujete, protože v pasu je adresa a vše ostatní. Víte, že čísla pasů jsou jedinečná, takže se cítíte dobře a implementujte tento systém.
Pak, o několik let později, zjistíte ošklivou pravdu:celá země čelí krizi identity.
Kdykoli někomu vyprší platnost pasu, dostane nový. Jejich identita se mění. Jiné systémy stále používají stará čísla pasů, takže nyní ukazují na duchy.
Jedinečnost nestačí. Hodnota se nesmí změnit po celou dobu životnosti řádku.
A pak zjistíte, že existují lidé, kteří nemají ani pasy. Nemůžete je zadat do systému, protože primární klíče nemohou být NULL
. Jak můžete někoho identifikovat pomocí NULL
klíč?
Každý řádek musí mít identifikátor. Hodnoty NULL nejsou povoleny.
Další iterace znamená nalezení identifikátoru, který se v průběhu času nemění a který má každý. V Indii se ukazuje, že jde o kartu Adhaar. V USA číslo sociálního zabezpečení.
Pokud vytváříte databázi, udělejte z nich primární klíče.
Někdy takový klíč nemáte. Vezměme si zemi, která ještě nemá číslo sociálního zabezpečení a která chce vytvořit digitální záznam každého občana. Mohli vytvořit nové SSN, nebo by mohli jen využít sílu databází a použít náhradní klíč.
Náhradní klíč nemá v reálném světě ekvivalent. Je to jen číslo uvnitř databáze. Takže máte tuto tabulku v nové zemi:
userID
First Name
Last Name
Passport Number
Čísla pasů jsou jedinečná. Kdykoli budete chtít získat identifikátor pro uživatele, můžete jej získat prostřednictvím čísla pasu.
ID uživatele se nikdy nemění. Číslo pasu se může změnit – ale vždy je jedinečné, takže vždy získáte správného uživatele. ID uživatele je náhradní pro neexistující číslo sociálního zabezpečení v této zemi.
Zábavný fakt:Číslo pasu je zde také klíč kandidáta. Mohl to být primární klíč, kdyby se nikdy nezměnil. Toto je rozdíl v obchodní logice.
Hlavní věc je následující:Kdykoli si vybíráte primární klíč, myslete na krizi identity . Je možné, že si někdo v budoucnu změní svůj identifikátor? Můžeme se dostat do stavu, kdy více lidí má stejný identifikátor?
Jako příklad používám lidi, protože to dělá identitu jasnější – víme, že každý člověk má mít identitu. Přeneste toto myšlení do svých databází. Všechno má identitu, což je přesně důvod, proč potřebujete primární klíče.
Poznámka:Někdy je možné a žádoucí použít více sloupců společně jako primární klíč. Toto je složený klíč.
Nyní se pokusíme definovat primární klíče pomocí skutečných příkladů kódu. Zde je třeba udělat dvě věci:nejprve identifikujete primární klíč. Poté se naučíte syntaxi pro jeho definování v databázi.
Příklad ze skutečného světa
Řekněme, že provozujete startup, podobně jako Flexport. Máte balíčky, které se potřebují dostat z jednoho místa na druhé, a lodě, které je přepravují. Dále máte zákazníky, kteří si objednávají tyto balíčky.
Zjistíte, že budete potřebovat jednu tabulku pro zákazníky, jednu pro balíčky a jednu pro přepravu, kde bude uvedeno, který balíček je kde právě teď.
Promyslete si, jaké sloupce budete potřebovat a jaký by měl být primární klíč. Pokud byste byli inženýrem ve společnosti Flexport, toto je skutečná otázka, kterou byste museli vyřešit. Nic není dáno, vše je objeveno v reálném světě.
Vzhledem k těmto informacím bych tyto tabulky navrhl takto:
Customers: first_name, last_name, email, address (for deliveries to their location)
Packages: weight, content
Transportation: <package_primary_key>, Port, time
Chybí nám primární klíče. Přemýšlejte o nich, než budete číst dále.
Pro balíček vyberu náhradní PackageID. Mohl jsem zkusit vypsat všechny atributy balíčku:hmotnost, objem, hustotu, stáří. Jednoznačně by identifikovali balíček, ale to je v praxi velmi obtížné. Lidi to nezajímá, jde jim jen o to, aby se balík dostal z jednoho místa na druhé.
Takže má smysl vytvořit náhodné číslo a použít ho jako ID. To je přesně důvod, proč vidíte, že FedEx, UPS a všechny doručovací služby používají čárové kódy a ID. Toto jsou náhradní klíče generované pro sledování zásilek.
Pro zákazníka vyberu náhradníka Zákaznické identifikační číslo. Zde jsem měl opět možnost vybrat si, řekněme, číslo sociálního pojištění svých zákazníků. Ale zákazníci to se mnou nechtějí sdílet, jen abych jim mohl něco poslat. Klíč tedy vygenerujeme interně, našim zákazníkům o tomto klíči neříkáme a nadále je nazýváme CustomerNo. 345681.
Zábavný příběh:Znám několik společností, kde toto zákaznické číslo odhalili, a zákazníci trvali na tom, aby dostali číslo 1. Bylo to docela zábavné - inženýři museli ve skutečnosti změnit svůj front-end kód na:if (cust == 345681) print(1);
Pro Přepravu vyberu kompozitní PackageID+Port+time. Tohle je o něco zajímavější. Mohl jsem vytvořit náhradníka i zde a fungovalo by to stejně dobře.
Ale tady je kouzlo indexování. Primární klíče získávají index automaticky, což znamená, že vyhledávání je mnohem efektivnější než primární klíče.
Když prohledáváte tuto databázi, většina dotazů bude mít formu "kde je tento balíček?". Jinými slovy, vzhledem k tomuto PackageID mi řekněte port a čas, na kterém se právě nachází. Potřeboval bych další index nad PackageID, pokud jej nemám jako součást svého primárního klíče.
Zní to dobře? Poslední krok, pojďme definovat tyto 3 tabulky v SQL. Syntaxe se mírně liší podle databáze, kterou používáte.
Definování primárních klíčů v 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.
);
Definování primárních klíčů v 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.
);
Moc se to neliší, že? Jakmile se seznámíte se základy, můžete je aplikovat na téměř jakoukoli databázi pouhým rychlým pohledem do dokumentace. Klíčem je vědět, co hledat!
Hodně štěstí, mladý padawane.
Užili jste si to? Také by se vám mohly líbit věci, které jsem se naučil od senior softwarového inženýra