Първичен ключ и външен ключ SQLite с примери

⚡ Умно обобщение

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

  • 🔑 Първичен ключ: Първичният ключ уникално идентифицира всеки ред и неговите стойности трябва да са уникални и никога да не са null.
  • 🧩 Композитен ключ: Комбинирането на две или повече колони образува съставен първичен ключ, когато никоя колона не е уникална.
  • 🔗 Външен ключ: Външен ключ препраща към ключ на родителска таблица и налага референтна цялост между свързани таблици.
  • ️ Активиране на прилагането: SQLite деактивира външните ключове по подразбиране, така че изпълнете PRAGMA foreign_keys = ON, за да ги активирате.
  • 🧱 Ограничения на колоните: Правилата NOT NULL, DEFAULT, UNIQUE и CHECK валидират стойностите, преди те да влязат в колона.
  • 🤖 AI помощ: Асистентите за преобразуване на текст в SQL с изкуствен интелект и GitHub Copilot генерират ключов и ограничен SQL от обикновен английски език.

Първичен ключ и външен ключ SQLite

Разделите по-долу обясняват SQLite ограниченията подробно, започвайки с PRIMARY KEY и FOREIGN KEY, които дефинират и свързват таблиците, и обхващайки правилата NOT NULL, DEFAULT, UNIQUE и CHECK, които валидират данните във всяка колона.

SQLite Ограничения

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

SQLite Първичен ключ

Всички стойности в колона с първичен ключ трябва да са уникални и да не са null. Първичният ключ уникално идентифицира всеки ред в таблицата.

Първичният ключ може да се приложи само към една колона или към комбинация от колони. В последния случай комбинацията от стойностите на колоните трябва да е уникална за всички редове на таблицата.

Синтаксис:

Има няколко различни начина за дефиниране на първичен ключ на таблица:

В самата дефиниция на колоната:

ColumnName INTEGER NOT NULL PRIMARY KEY;

Като отделна дефиниция:

PRIMARY KEY(ColumnName);

За да създадете комбинация от колони като първичен ключ:

PRIMARY KEY(ColumnName1, ColumnName2);

SQLite Ограничения NOT NULL, DEFAULT, UNIQUE и CHECK

Освен първичния ключ, SQLite предоставя няколко ограничения за колони, които валидират стойностите, въведени в таблица. Ограниченията NOT NULL, DEFAULT, UNIQUE и CHECK са дефинирани в дефиницията на колоната и всяко едно от тях налага специфично правило върху стойностите на колоната. тип данни и ценности.

Ограничение NOT NULL

- SQLite Ограничението NOT NULL не позволява на колоната да има null стойност:

ColumnName INTEGER  NOT NULL;

Ограничение ПО ПОДРАЗБИРАНЕ

С SQLite Ограничение ПО СТАНДАРТНО, ако не вмъкнете никаква стойност в колона, вместо това се вмъква стойността по подразбиране.

Например:

ColumnName INTEGER DEFAULT 0;

Ако напишете оператор за вмъкване и не укажете никаква стойност за тази колона, колоната ще има стойност 0.

УНИКАЛНО ограничение

- SQLite Ограничението UNIQUE предотвратява дублирането на стойности сред всички стойности в колоната.

Например:

EmployeeId INTEGER NOT NULL UNIQUE;

Това налага стойността „EmployeeId“ да бъде уникална; не се допускат дублирани стойности. Обърнете внимание, че това се отнася само за стойностите на колоната „EmployeeId“.

ПРОВЕРЕТЕ ограничение

- SQLite Ограничението CHECK задава условие за проверка на вмъкната стойност. Ако стойността не отговаря на условието, тя няма да бъде вмъкната.

Quantity INTEGER NOT NULL CHECK(Quantity > 10);

Не можете да въведете стойност по-малка от 10 в колоната „Количество“.

SQLite Чужд ключ

- SQLite Външният ключ е ограничение, което проверява съществуването на стойност, присъстваща в една таблица, в друга таблица, която има връзка с първата таблица, където е дефиниран външният ключ.

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

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

Обърнете внимание, че ограниченията на външния ключ не са активирани по подразбиране в SQLiteПърво трябва да ги активирате, като изпълните следната команда:

PRAGMA foreign_keys = ON;

Въведени са ограничения за външен ключ SQLite започвайки от версия 3.6.19.

Пример за SQLite Чужд ключ

Да предположим, че имаме две таблици: „Студенти“ и „Отдели“.

Таблицата „Студенти“ съдържа списък със студенти, а таблицата „Отдели“ съдържа списък с катедрите. Всеки студент принадлежи към катедра; т.е. всеки студент има колона departmentId.

Сега ще видим как ограничението на външния ключ може да бъде полезно, за да се гарантира, че стойността на идентификатора на отдела в таблицата „Студенти“ трябва да съществува в таблицата „Отдели“.

Така че, ако създадем ограничение на външен ключ за DepartmentId в таблицата Students, всеки вмъкнат departmentId трябва да присъства в таблицата Departments.

CREATE TABLE [Departments] (
	[DepartmentId] INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT,
	[DepartmentName] NVARCHAR(50)  NULL
);
CREATE TABLE [Students] (
	[StudentId] INTEGER  PRIMARY KEY AUTOINCREMENT NOT NULL,
	[StudentName] NVARCHAR(50)  NULL,
	[DepartmentId] INTEGER  NOT NULL,
	[DateOfBirth] DATE  NULL,
	FOREIGN KEY(DepartmentId) REFERENCES Departments(DepartmentId)
);

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

В този пример таблицата „Отдели“ има връзка с таблицата „Студенти“ чрез външен ключ, така че всяка стойност на departmentId, вмъкната в таблицата „Студенти“, трябва да съществува в таблицата „Отдели“. Ако се опитате да вмъкнете стойност на departmentId, която не съществува в таблицата „Отдели“, ограничението на външния ключ ще ви попречи да направите това.

Нека вмъкнем два отдела, „ИТ“ и „Изкуства“, в таблицата „Отдели“ със следното ВМЪКВАНЕ на заявки:

INSERT INTO Departments VALUES(1, 'IT');
INSERT INTO Departments VALUES(2, 'Arts');

Двете оператори трябва да вмъкнат два отдела в таблицата „Отдели“. Можете да потвърдите, че двете стойности са вмъкнати, като изпълните след това заявката „SELECT * FROM Отдели“:

Резултат от заявка SELECT, показващ отделите по информационни технологии и изкуства в SQLite

След това опитайте да вмъкнете нов студент с departmentId, който не съществува в таблицата Departments:

INSERT INTO Students(StudentName,DepartmentId) VALUES('John', 5);

Редът няма да бъде вмъкнат и ще получите грешка, която гласи: Ограничението FOREIGN KEY е неуспешно.

SQLite Съобщение за грешка „Неуспешно ограничение на FOREIGN KEY“

Разлика между първичен ключ и външен ключ в SQLite

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

База Първичен ключ Чужд ключ
Цел Уникално идентифицира всеки ред в отделната му таблица Препраща към първичния ключ на друга таблица, за да ги свърже
Уникалност Стойностите трябва да са уникални Стойностите могат да се повтарят, така че много дъщерни редове могат да споделят един родителски ред
Нулеви стойности Не може да бъде нула Може да бъде null, когато връзката е по избор
Брой на маса Само един първичен ключ на таблица Една таблица може да има няколко външни ключа
Индексирането Индексирано автоматично Не се индексира автоматично; добавете едно за по-добра производителност

В примера със Студенти и Отдели, DepartmentId е основният ключ на таблицата Отдели и външен ключ в таблицата Студенти, който свързва всеки студент с валиден отдел.

SQLite Съставен първичен ключ

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

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

CREATE TABLE Enrollments (
	StudentId INTEGER NOT NULL,
	CourseId INTEGER NOT NULL,
	Grade TEXT,
	PRIMARY KEY (StudentId, CourseId)
);

Тук нито StudentId, нито CourseId са уникални поотделно, но двойката (StudentId, CourseId) е уникална, така че един и същ студент не може да бъде записан в един и същ курс два пъти. Обърнете внимание на следните точки, когато използвате съставен ключ:

  • Използвайте съставен ключ, когато една колона не може еднозначно да идентифицира ред.
  • Всяка колона в съставния ключ следва правилата за първичен ключ, така че комбинираната стойност трябва да е уникална и да не е null.
  • Съставният ключ се записва като отделна клауза PRIMARY KEY на ниво таблица, а не в дефиниция на една колона.

SQLite Действия с външен ключ: ON DELETE и ON UPDATE

Външен ключ може също да контролира какво се случва с дъщерните редове, когато родителският ред, към който се позовават, бъде изтрит или актуализиран. Тези действия за препращане се добавят с клаузите ON DELETE и ON UPDATE, когато дефинирате външния ключ. SQLite подкрепя пет действия:

  • НЯМА ДЕЙСТВИЕ — действието по подразбиране, което повдига грешка, ако дъщерните редове все още препращат към родителския.
  • ОГРАНИЧАВАНЕ — предотвратява незабавното изтриване или актуализиране, преди да се изпълни каквато и да е друга промяна.
  • SET NULL — задава дъщерната колона с външен ключ на null.
  • ЗАДЪЛЖИТЕЛНО — задава колоната с външен ключ на дъщерния елемент на декларираната ѝ стойност по подразбиране.
  • КАСКАДА — прилага същата промяна към дъщерните редове, така че изтриването на родител изтрива и неговите деца.

Примерът по-долу пресъздава таблицата „Студенти“, така че изтриването на отдел автоматично изтрива неговите студенти, а актуализирането на идентификатора на отдел актуализира съответстващите студенти:

CREATE TABLE Students (
	StudentId INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
	StudentName NVARCHAR(50) NULL,
	DepartmentId INTEGER NOT NULL,
	FOREIGN KEY(DepartmentId) REFERENCES Departments(DepartmentId)
		ON DELETE CASCADE
		ON UPDATE CASCADE
);

Не забравяйте, че референтните действия се изпълняват само когато е включена поддръжката на външни ключове, така че изпълнявайте PRAGMA foreign_keys = ON в началото на всяка връзка. Без нея, SQLite анализира клаузите ON DELETE и ON UPDATE, но не ги прилага.

Въпроси и Отговори

Да. Когато една колона е декларирана точно като INTEGER PRIMARY KEY, тя става псевдоним за вградения rowid на таблицата. SQLite не поддържа отделен индекс за него, така че търсенията по този ключ са бързи и не използват допълнително място за съхранение.

Прилагането на външни ключове е изключено по подразбиране, за да се запази обратната съвместимост с по-стари бази данни и скриптове, написани преди версия 3.6.19. Всяка връзка с базата данни трябва да изпълни PRAGMA foreign_keys = ON преди SQLite започва проверка на ограниченията на външния ключ.

SQLite индексира автоматично първичните ключове и колоните UNIQUE, но не индексира колоните с външен ключ. Тъй като дъщерната колона се чете при всяка проверка на ограниченията, за по-висока производителност се препоръчва създаването на собствен индекс за всяка колона с външен ключ.

Не. ПРОМЕНИ ТАБЛИЦАТА в SQLite Не можете да добавите първичен ключ или външен ключ към съществуваща таблица. Преименувате старата таблица, създавате нова таблица с дефинирания ключ, копирате редовете с INSERT SELECT и след това премахвате старата таблица.

Обикновен ЦЯЛОЧИСЛЕН ПЪРВИЧЕН КЛЮЧ (INTEGER PRIMARY KEY) присвоява следващия идентификатор като един над най-големия съществуващ идентификатор на ред и може да използва повторно идентификаторите след изтриване. tracks е най-високият идентификатор, използван някога в sqlite_sequence, и никога не използва повторно стойност, с малка цена на производителност.

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

Да. Асистентите за преобразуване на текст в SQL с изкуствен интелект преобразуват описание на вашите таблици на разбираем английски език в оператори CREATE TABLE с клаузи PRIMARY KEY и FOREIGN KEY. Предоставянето на съществуващата схема подобрява точността и генерираният SQL винаги трябва да се преглежда преди изпълнение върху реални данни.

Да. Копилот на GitHub предлага CREATE TABLE код с PRIMARY KEY, FOREIGN KEY и други ограничения, вградени в редакторите, като например VS CodeТой чете съществуващата ви схема и миграции, така че неговите завършвания използват повторно реалните ви имена на таблици и колони.

Обобщете тази публикация с: