Mysql
 sql >> база данни >  >> RDS >> Mysql

SQL урок за първичен ключ – Как да дефинирате първичен ключ в база данни

Всяка велика история започва с криза на идентичността. Люк, великият майстор джедай, започва да не е сигурен - „Кой съм аз?“ - и как мога да бъда някой важен? Необходим е Йода, този със Силата, за да го научи как да използва силите си.

Днес, позволете ми да бъда вашият Йода.

Ще започнем с това как да изберем първичен ключ, да се борим с кризата на идентичността и след това да завършим с примерни кодове за създаване на първичен ключ в база данни.

Как да изберем първичен ключ

Може да си мислите, че Люк е единственият с криза на идентичността, но това не е вярно. При създаването на база данни всичко е в криза на идентичността. И точно затова имаме нужда от първични ключове:те решават кризата. Те ни казват как да намерим всички.

Представете си, че сте правителството и искате да идентифицирате всеки един от вашите граждани цифрово. И така, вие създавате тази база данни с всичко за тях:

First Name
Last Name
Passport Number

Избирате номера на паспорта като първичен ключ - самоличността за всеки. Мислите, че това е всичко, от което се нуждаете, тъй като в паспорта има адрес и всичко останало. Знаете, че номерата на паспортите са уникални, така че се чувствате добре и прилагайте тази система.

След това, няколко години по-късно, разбирате една грозна истина:цялата страна е изправена пред криза на идентичността.

Когато нечий паспорт изтича, той получава нов. Идентичността им се променя. Други системи продължават да използват старите номера на паспортите, така че вече сочат към хора-призраци.

Уникалността не е достатъчна. Стойността не трябва да се променя през целия живот на реда.

И тогава откривате, че има хора, които дори нямат паспорти. Не можете да ги въведете във вашата система, тъй като първичните ключове не могат да бъдат NULL . Как можете да идентифицирате някого с NULL ключ?

Всеки ред трябва да има идентификатор. NULL не са разрешени.

Следващата итерация означава намиране на идентификатор, който не се променя с течение на времето и който всеки има. В Индия това се оказва картата Adhaar. В САЩ социалноосигурителният номер.

Ако създавате база данни, направете ги вашите първични ключове.

Понякога нямате такъв ключ. Помислете за държава, която все още няма социалноосигурителен номер и те искат да създадат цифров запис на всеки гражданин. Те биха могли да създадат нов SSN или просто да използват силата на базите данни и да използват сурогатен ключ.

Сурогатният ключ няма еквивалент в реалния свят. Това е просто число в база данни. И така, имате тази таблица в новата държава:

userID
First Name
Last Name
Passport Number

Паспортните номера са уникални. Винаги, когато искате да получите идентификатора за потребител, можете да го получите чрез номера на паспорта.

UserID никога не се променя. Номерът на паспорта може да се променя - но той винаги е уникален, така че винаги получавате правилния потребител. UserID е сурогат за несъществуващ социалноосигурителен номер в тази държава.

Забавен факт:Номерът на паспорта тук също е ключ за кандидат. Можеше да е първичният ключ, ако никога не се променяше. Това е разграничение на бизнес логиката.

Основният извод е следният:Всеки път, когато избирате първичен ключ, помислете за криза на идентичността . Възможно ли е някой да промени идентификатора си в бъдеще? Можем ли да влезем в състояние с множество хора с един и същ идентификатор?

Използвам хората като пример, защото това прави идентичността по-ясна – знаем, че всеки човек трябва да има идентичност. Прехвърлете това мислене във вашите бази данни. Всичко има идентичност, точно затова имате нужда от първични ключове.

Забележка:Понякога е възможно и желателно да използвате няколко колони заедно като първичен ключ. Това е композитен ключ.

Сега нека опитаме да дефинираме първични ключове с реални примери за код. Тук трябва да направите две неща:първо, ще идентифицирате първичния ключ. След това ще научите синтаксиса за дефинирането му в база данни.

Пример от реалния свят

Да кажем, че стартирате стартиране на доставка, подобно на Flexport. Имате пакети, които трябва да стигнат от едно място на друго, и кораби, които ги транспортират. Освен това имате клиенти, които поръчват тези пакети.

Смятате, че ще ви трябва една таблица за клиентите, една за пакетите и една за транспортиране, показвайки кой пакет къде се намира в момента.

Помислете какви колони ще ви трябват и какъв трябва да бъде първичният ключ. Ако бяхте инженер във Flexport, това е действителен въпрос, който ще трябва да разберете. Нищо не е дадено, всичко се открива в реалния свят.

Като се има предвид тази информация, бих проектирал тези таблици така:

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

Липсват ни първичните ключове. Помислете за тях, преди да прочетете повече.

За пакета ще избера сурогат PackageID. Можех да се опитам да изброя всички атрибути на опаковката:тегло, обем, плътност, възраст. Те биха идентифицирали уникално пакета, но това е много трудно да се направи на практика. Хората не се интересуват от това, те просто се интересуват от това, че пакетът ще стигне от едно място на друго.

Така че има смисъл да създадете произволно число и да го използвате като идентификатор. Точно затова виждате, че FedEx, UPS и всяка служба за доставка използват баркодове и идентификационни номера. Това са сурогатни ключове, генерирани за проследяване на пакети.

За клиента ще избера сурогат Клиентски номер. Тук отново имах възможност да избера, да речем, социалноосигурителния номер на моите клиенти. Но клиентите не искат да споделят това с мен, само за да мога да им изпратя нещо. По този начин ние генерираме ключ вътрешно, не казваме на нашите клиенти за този ключ и продължаваме да ги наричаме CustomerNo. 345681.

Забавна история:Познавам няколко компании, в които разкриха този CustomerNo, и клиентите настояваха да получат номер 1. Беше доста забавно – инженерите всъщност трябваше да променят своя преден код на:if (cust == 345681) print(1);

За транспорт ще избера композит PackageID+Port+time. Това е малко по-интересно. Можех да създам сурогат и тук и ще работи също толкова добре.

Но тук се крие магията на индексирането. Първичните ключове получават индекс автоматично, което означава, че търсенето е много по-ефективно спрямо първичните ключове.

Когато търсите в тази база данни, повечето заявки ще бъдат от формата "къде е този пакет?". С други думи, като се има предвид този PackageID, кажете ми пристанището и времето, в което е в момента. Ще ми трябва допълнителен индекс върху PackageID, ако го нямам като част от моя първичен ключ.

Това добре ли звучи? Последна стъпка, нека дефинираме тези 3 таблици в SQL. Синтаксисът варира леко в зависимост от базата данни, която използвате.

Дефиниране на първични ключове в 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.

);

Дефиниране на първични ключове в 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.

);

Не е много различно, нали? След като разберете основите, можете да го приложите към почти всяка база данни само с бърз поглед към документацията. Ключът е да знаете какво да търсите!

Успех, млад падаван.

Наслаждавахте се на това? Може също да харесате Неща, които научих от старши софтуерен инженер



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Актуализиране на данни в MySQL база данни

  2. 5 начина да проверите дали таблица съществува в MySQL

  3. Какво означава, когато MySQL е в състояние Изпращане на данни?

  4. MySQL срещу MariaDB

  5. Промяна на десетичния разделител в MySQL