Оператор SQL PRIMARY KEY
Оператор SQL PRIMARY KEY (Первичный ключ) — это параметр, который устанавливается для однозначной идентификации той или иной записи в таблице. Значения SQL PRIMARY KEY должны быть всегда уникальны, а так же не содержать значений NULL.
Любая таблица обязана иметь Первичный ключ, по которому можно однозначно идентифицировать записи в ней.
Оператор SQL PRIMARY KEY имеет следующий синтаксис:
Для MySQL:
CREATE TABLE table_name ( Id int NOT NULL, PRIMARY KEY (Id) )
Для MS SQL Server, Oracle, MS Access:
CREATE TABLE table_name ( Id int NOT NULL PRIMARY KEY )
Примеры оператора SQL PRIMARY KEY. Используя оператор SQL PRIMARY KEY, по аналогии с примером 1 оператора SQL CREATE создать таблицу Planets с Первичным ключом ID:
Решение для MySQL:
CREATE TABLE Planets ( ID int NOT NULL, PlanetName varchar(10), Radius float (10), SunSeason float(10), OpeningYear int, HavingRings bit, Opener varchar(30) PRIMARY KEY (ID) )
Решение для MS SQL Server, Oracle, MS Access:
CREATE TABLE Planets ( ID int NOT NULL PRIMARY KEY, PlanetName varchar(10), Radius float (10), SunSeason float(10), OpeningYear int, HavingRings bit, Opener varchar(30) )
SQL PRIMARY KEY
Ограничение PRIMARY KEY однозначно идентифицирует каждую запись в таблице.
Первичные ключи должны содержать уникальные значения и не могут содержать нулевые значения.
Таблица может иметь только один первичный ключ, а в таблице этот первичный ключ может состоять из одного или нескольких столбцов (полей).
PRIMARY KEY в CREATE TABLE
Следующий SQL создает первичный ключ о «ID» в столбик, когда таблица «Persons» создается:
CREATE TABLE Persons (
ID int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Age int,
PRIMARY KEY (ID)
);
SQL Server / Oracle / MS Access:
CREATE TABLE Persons (
ID int NOT NULL PRIMARY KEY,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Age int
);
Чтобы разрешить именование ограничения первичного ключа и определить ограничение первичного ключа для нескольких столбцов, используйте следующий синтаксис SQL:
MySQL / SQL Server / Oracle / MS Access:
CREATE TABLE Persons (
ID int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Age int,
CONSTRAINT PK_Person PRIMARY KEY (ID,LastName)
);
Примечание: В приведенном выше примере существует только один первичный ключ (PK_Person). Однако значение первичного ключа состоит из двух столбцов (ID + LastName).
PRIMARY KEY в ALTER TABLE
Чтобы создать ограничение первичного ключа для столбца «ID», когда таблица уже создана, используйте следующий SQL:
MySQL / SQL Server / Oracle / MS Access:
ALTER TABLE Persons
ADD PRIMARY KEY (ID);
Чтобы разрешить именование ограничения первичного ключа и определить ограничение первичного ключа для нескольких столбцов, используйте следующий синтаксис SQL:
MySQL / SQL Server / Oracle / MS Access:
ALTER TABLE Persons
ADD CONSTRAINT PK_Person PRIMARY KEY (ID,LastName);
Примечание: Если вы используете инструкцию ALTER TABLE для добавления первичного ключа, то столбец(ы) первичного ключа должен(ы) быть уже объявлено, что они не содержат нулевых значений (при первом создании таблицы).
Ограничение PRIMARY KEY с DROP
Чтобы удалить ограничение первичного ключа, используйте следующий SQL:
ALTER TABLE Persons
DROP PRIMARY KEY;
SQL Server / Oracle / MS Access:
ALTER TABLE Persons
DROP CONSTRAINT PK_Person;
Мы только что запустили
SchoolsW3 видео
курс сегодня!
Сообщить об ошибке
Если вы хотите сообщить об ошибке или внести предложение, не стесняйтесь отправлять на электронное письмо:
Ваше предложение:
Спасибо Вам за то, что помогаете!
Ваше сообщение было отправлено в SchoolsW3.
ТОП Учебники
ТОП Справочники
ТОП Примеры
SchoolsW3 оптимизирован для бесплатного обучения, проверки и подготовки знаний. Примеры в редакторе упрощают и улучшают чтение и базовое понимание. Учебники, ссылки, примеры постоянно пересматриваются, чтобы избежать ошибок, но не возможно гарантировать полную правильность всего содержания. Некоторые страницы сайта могут быть не переведены на РУССКИЙ язык, можно отправить страницу как ошибку, так же можете самостоятельно заняться переводом. Используя данный сайт, вы соглашаетесь прочитать и принять Условия к использованию, Cookies и политика конфиденциальности.
Зачем нужен PRIMARY KEY и FOREIGN KEY (ключи)?
Разумеется, я читал основы SQL, но они не объясняют зачем нужны эти ключи в работе БД. Первичный ключ ID содержит уникальное значение по которому можно однозначно идентифицировать запись. Тут первичный ключ ID. Внешний ключ dept_name. Зачем мы пишем перед полем PRIMARY KEY т.е. указываем что это поле первичный ключ? Почему нельзя сделать это поле просто автоинкрементируемым? И будет уникальное поле. Аналогично — зачем мы пишем перед полем dept_name FOREIGN KEY? То есть мы говорим, что поле dept_name указывает на поле dept_name в другой таблице department. Что это дает? Я могу не указывать FOREIGN KEY (dept_name) REFERENCES department(dept_name) при создании таблицы. Просто запомнить, что например JOIN по этим полям. Что делают эти команды? Зачем они нужны?
Отслеживать
задан 15 дек 2022 в 21:57
195 2 2 серебряных знака 10 10 бронзовых знаков
О какой СУБД речь?
15 дек 2022 в 22:02
Автоинкрементируемое поле можно изменить UPDATE-запросом, и есть риск, что оно перестанет быть уникальным. PRIMARY KEY не позволит изменить его на уникальное значение
15 дек 2022 в 22:04
FOREIGN KEY запретит удаление строки́ из department, если в instructor ещё есть стро́ки, которые ссылаются на строку, которую пытались удалить
15 дек 2022 в 22:05
@andreymal Или удалять все записи по ключу из таблицы instructor. В то же время запретят вставку записей в instructor если в department нет соответствующего ключа
15 дек 2022 в 22:09
Почему нельзя сделать это поле просто автоинкрементируемым? И будет уникальное поле. Можно. Только в этом случае ничто не мешает сунуть в это поле NULL. в сотню записей.
16 дек 2022 в 7:17
5 ответов 5
Сортировка: Сброс на вариант по умолчанию
Либо плохо читали, либо читали что-то не то. По пунктам.
PRIMARY KEY. Как выше уже сказали, identity-поле вовсе не гарантирует уникальность значения. Пример ниже — для MS SQL. Создаем таблицу, и добавляем в неё 1 строку:
use tempdb go create table dbo.pk_test ( id int identity not null, name varchar(1) ) go insert into dbo.pk_test(name) values('A'); select id, name from dbo.pk_test; go id name ----------- ---- 1 A (1 rows affected)
и вставляем ещё одну с таким же id:
begin tran; set xact_abort on; set identity_insert dbo.pk_test on; insert into dbo.pk_test(id, name) values(1, 'B'); set identity_insert dbo.pk_test off; select id, name from dbo.pk_test; go id name ----------- ---- 1 A 1 B (2 rows affected)
– никаких ошибок. Откатываем вставку, вешаем на поле id PRIMARY KEY:
rollback go alter table dbo.pk_test add constraint pk_pk_test primary key(id); go select id, name from dbo.pk_test; go id name ----------- ---- 1 A (1 rows affected)
и снова пытаемся вставить дубль id:
begin tran; set xact_abort on; set identity_insert dbo.pk_test on; insert into dbo.pk_test(id, name) values(1, 'B'); go Violation of PRIMARY KEY constraint 'pk_pk_test'. Cannot insert duplicate key in object 'dbo.pk_test'.
– получаем ошибку. А в некоторых БД identity-поля отсутствуют вообще — например, в оракле до версии 12c. Вместо них используются генераторы последовательностей (sequence), и для вставки неуникального значения в поле не нужно никаких ухищрений типа set identity_insert. И ещё нюанс PRIMARY/UNIQUE constraints: по сути, это логические ограничения, ограничения бизнес-модели. На физическом уровне эти ограничения всегда реализуются уникальными индексами по соответствующим полям.
FOREIGN KEY: создаем и заполняем тестовые таблицы:
use tempdb go create table dbo.fk_source ( id int not null primary key ) go create table dbo.fk_target ( fk_id int not null, constraint fk_target_source foreign key(fk_id) references dbo.fk_source(id) on update cascade on delete no action ) go insert into dbo.fk_source(id) values(1); insert into dbo.fk_target(fk_id) values(1); go select id from dbo.fk_source; go id ----------- 1 (1 rows affected) select fk_id from dbo.fk_target; go fk_id ----------- 1 (1 rows affected)
теперь в таблице, на которую ссылается FK, меняем значение поля с FK:
update dbo.fk_source set where rows affected) select fk_id from dbo.fk_target go fk_id ----------- 2 (1 rows affected)
– из-за включенной опции каскадного обновления в связанной таблице значение поля обновилось автоматически. Пытаемся удалить запись из таблицы-источника:
delete dbo.fk_source where 547, Level 16, State 1, Server ., Line 1 The DELETE statement conflicted with the REFERENCE constraint "fk_target_source". The conflict occurred in database "tempdb", table "dbo.fk_target", column 'fk_id'. The statement has been terminated.
– FK не позволяет этого сделать. Пытаемся в таблицу-приёмник вставить не существующее в таблице-источнике значение:
insert into dbo.fk_target(fk_id) values(3); go Msg 547, Level 16, State 1, Server ., Line 1 The INSERT statement conflicted with the FOREIGN KEY constraint "fk_target_source". The conflict occurred in database "tempdb", table "dbo.fk_source", column 'id'. The statement has been terminated.
– FK не позволяет этого сделать. Пытаемся очистить всю таблицу-источник, и вообще удалить её:
truncate table dbo.fk_source; go Msg 4712, Level 16, State 1, Server ., Line 1 Cannot truncate table 'dbo.fk_source' because it is being referenced by a FOREIGN KEY constraint. drop table dbo.fk_source; go Msg 3726, Level 16, State 1, Server ., Line 1 Could not drop object 'dbo.fk_source' because it is referenced by a FOREIGN KEY constraint.
– FK не позволяет этого сделать. А теперь удаляем FK:
alter table dbo.fk_target drop constraint fk_target_source go
– и становится можно всё:
insert into dbo.fk_target(fk_id) values(3); go (1 rows affected) delete dbo.fk_source where rows affected) truncate table dbo.fk_source; go drop table dbo.fk_source; go
Отслеживать
ответ дан 16 дек 2022 в 4:26
user532595 user532595
Помимо вышеуказанных причин приведу ещё одну: PRIMARY KEY и FOREIGN KEY зачастую индексируются. Это приводит к тому, что обращение по ним будет происходить быстрее.
Пример на MySql:
Создадим таблицу и заполним её большим числом данных:
CREATE TABLE `table_test_1` ( `field_1` INT NOT NULL AUTO_INCREMENT, `field_2` INT NOT NULL DEFAULT 0, `field_3` VARCHAR(255) NOT NULL, PRIMARY KEY (`field_1`) ); INSERT INTO `table_test_1` (`field_3`) VALUES ('a1'),('a2'),('a3'); INSERT INTO `table_test_1` (`field_3`) VALUES ('b1'),('b2'),('b3'); INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; INSERT INTO `table_test_1` (`field_3`) SELECT `field_3` FROM `table_test_1`; UPDATE `table_test_1` SET `field_2` = `field_1`;
Теперь у нас есть таблица с первичным ключом field_1 и аналогичным ему значением field_2 . Теперь сравним выборки по первичному ключу:
SELECT * FROM `table_test_1` WHERE `field_1` = 555555; +---------+---------+---------+ | field_1 | field_2 | field_3 | +---------+---------+---------+ | 555555 | 555555 | b2 | +---------+---------+---------+ 1 row in set (0.00 sec)
SELECT * FROM `table_test_1` WHERE `field_2` = 555555; +---------+---------+---------+ | field_1 | field_2 | field_3 | +---------+---------+---------+ | 555555 | 555555 | b2 | +---------+---------+---------+ 1 row in set (0.36 sec)
Теперь создадим вторую таблицу:
CREATE TABLE `table_test_2` ( `field_1` INT NOT NULL AUTO_INCREMENT, `field_2` INT NOT NULL DEFAULT 0, `field_3` INT NULL DEFAULT NULL, PRIMARY KEY (`field_1`), CONSTRAINT `table_test_2_fk0` FOREIGN KEY (`field_3`) REFERENCES `table_test_1` (`field_1`) ON UPDATE RESTRICT ON DELETE RESTRICT ); INSERT INTO `table_test_2` (`field_1`, `field_2`, `field_3`) SELECT `field_1`, `field_1` FROM `table_test_1`;
Здесь у нас есть внешний ключ field_3 и обычное поле field_2 , значения которых содержит значения field_1 (и соответственно field_2 ) из первой таблицы.
Попробуем INNER JOIN запрос на основе внешнего ключа:
SELECT * FROM `table_test_2` INNER JOIN `table_test_1` ON `table_test_2`.`field_3` = `table_test_1`.`field_1` LIMIT 1 OFFSET 55555; +---------+---------+---------+---------+---------+---------+ | field_1 | field_2 | field_3 | field_1 | field_2 | field_3 | +---------+---------+---------+---------+---------+---------+ | 71925 | 71925 | 71925 | 71925 | 71925 | a2 | +---------+---------+---------+---------+---------+---------+ 1 row in set (0.28 sec)
А вот запрос на основе обычных значений:
SELECT * FROM `table_test_2` INNER JOIN `table_test_1` ON `table_test_2`.`field_2` = `table_test_1`.`field_2` LIMIT 1 OFFSET 55555; +---------+---------+---------+---------+---------+---------+ | field_1 | field_2 | field_3 | field_1 | field_2 | field_3 | +---------+---------+---------+---------+---------+---------+ | 71925 | 71925 | 71925 | 71925 | 71925 | a2 | +---------+---------+---------+---------+---------+---------+ 1 row in set (0.51 sec)
Возможно эти примеры не самые показательные, но разница заметна уже на них, а для сложных структур данных и для более сложных запросов разница между индексируемыми значениями и неиндексируемыми становится критически важной.
Первичный ключ (PRIMARY KEY) в SQL
В SQL ограничение PRIMARY KEY используется для уникальной идентификации строк.
Ограничение PRIMARY KEY — это просто комбинация ограничений NOT NULL и UNIQUE. Это означает, что столбец не может содержать повторяющиеся значения, а также значения NULL .
Синтаксис создания первичного ключа:
CREATE TABLE Colleges (
college_id INT ,
college_code VARCHAR ( 20 ) NOT NULL ,
college_name VARCHAR ( 50 ) ,
CONSTRAINT CollegePK PRIMARY KEY ( college_id )
Здесь столбец college_id имеет первичный ключ. Это означает, что значения этого столбца должны быть уникальными, а также не содержать значения NULL .
Примечание: Синтаксис создания первичного ключа может отличаться в некоторых СУБД.
Ошибка первичного ключа
Если мы попытаемся вставить нулевые или повторяющиеся значения в столбец с первичным ключом, то получим ошибку. Например: