Как создать первичный ключ в sql. SQL – Primary Key (Первичный ключ)

Представляю Вашему вниманию вольный перевод статьи SQL for Beginners Part 2

Для каждого веб-разработчика важно уметь взаимодействовать с базами данных. Во второй части мы продолжаем изучение языка SQL и применяем свои навыки к СУБД MySQL . Мы познакомимся с индексами, типами данных и более сложными запросами.

Что вам нужно

Обратитесь, пожалуйста, к разделу "Что вам нужно" первой части, которая находится .

Если Вы хотите выполнять приведенные примеры на своем сервере, сделайте следующее:

  1. Откройте консоль MySQL и авторизуйтесь.
  2. Создайте базу "my_first_db" с помощью запроса CREATE , если она не была создана ранее.
  3. Смените базу, используя оператор USE .

Индексы

Индексы (или ключи) обычно используются для повышения скорости выполнения операторов, которые выбирают данные (такие как SELECT ) из таблиц.

Они являются важной частью хорошей архитектуры баз данных, сложно их отнести к "оптимизации". Обычно индексы добавляются изначально, но могут быть добавлены позднее с помощью запроса ALTER TABLE .

Основные доводы в пользу индексации столбцов базы данных:

  • Почти каждая таблица имеет первичный ключ (PRIMARY KEY ), обычно это столбец "id".
  • Если в столбце предполагается хранить уникальные значения, он должен иметь уникальный индекс (UNIQUE ).
  • Если нужен частый поиск по столбцу (его использование в предложении WHERE ), он должен иметь обычный индекс (INDEX ).
  • Если столбец используется для взаимосвязи с другой таблицей, он должен быть по возможности внешним ключом (FOREIGN KEY ) или обычным индексом.

Первичный ключ (PRIMARY KEY)

Почти у всех таблиц есть первичный ключ, обычно это целое число с опцией автоинкремента (AUTO_INCREMET ).

Очень часто подзапросы ведут к значительному снижению производительности, поэтому используйте их с осторожностью.

UNION: Совмещение данных

Используя запрос UNION , можно объединять результаты нескольких напросов SELECT.

В этом примере объединяются штаты, название которых начинается с буквы "N", со штатами с большим населением:

(SELECT * FROM states WHERE name LIKE "n%") UNION (SELECT * FROM states WHERE population > 10000000);

Обратите внимание, что штат New York принадлежит крупным и начинается с буквы "N". Однако в списке он встречается один раз, т.к. дубликаты удаляются автоматически.

Так же прелесть запросов UNION заключается в том, что их можно использовать для объединения запросов к разным таблицам.

Например, у нас есть таблицы employees (сотрудники), managers (менеджеры) и customers (клиенты). В каждой таблице есть поле с адресом электронной почты. Если мы хотим получить все E-mail адреса в одном запросе, то можем поступить следующим образом:

(SELECT email FROM employees) UNION (SELECT email FROM managers) UNION (SELECT email FROM customers WHERE subscribed = 1);

Выполнив этот запрос, мы получим почтовые адреса всех сотрудников и менеджеров, и только тех клиентов, которые подписаны на рассылку.

INSERT Продолжение

Мы уже говорили о запросе INSERT в предыдущей статье. После того как мы рассмотрели индексы, мы можем поговорить о дополнительных возможностях запросов INSERT .

INSERT ... ON DUPLICATE KEY UPDATE

Это наиболее часто используемое условие. Сначала запрос пытается выполнить INSERT , и если запрос терпит неудачу в следствии дублирования первичного (PRIMARY KEY ) или уникального (UNIQUE KEY ) ключа, то выполняется запрос UPDATE .

Давайте сначала создадим тестовую таблицу.

Это таблица для хранения продуктов. Поле "stock" хранит количество продуктов доступных на складе.

Теперь попробуем вставить уже существующее значение в таблицу и посмотрим что произойдет.

Мы получили ошибку.

Допустим, мы получили новую хлебопекарню и хотим обновить базу данных, но не знаем есть ли уже запись в базе данных. Мы можем сначала проверить существование записи, а потом выполнить другой запрос для вставки. Или можно выполнить все в одном простом запросе:

Работает также как и INSERT , но с одной важной особенностью. Если запись уже существует, то она удаляется, а потом выполняется запрос INSERT , при этом мы не получим никаких сообщений об ошибке.

Обратите внимание, т.к. вставляется совершенно новая строка, поле автоинкремента увеличивается на единицу.

Это способ предотвращения появления ошибки о дублировании, прежде всего для того, чтобы не останавливать выполнение приложения. Может понадобится вставить новую строку без вывода каких-либо ошибок, если даже произошло дублирование.

Нет никаких ошибок и обновленных строк.

Типы данных

Каждый столбец в таблице должен быть определенного типа. Мы уже использовали типы INT , VARCHAR и DATE , но не останавливались на них подробно. Также мы рассмотрим еще несколько типов данных.

Начнем с числовых типов данных. Я разделяю из на две группы: Целые и дробные.

Целые

Столбец с типом целые может хранить только натуральные числа (без десятичной точки). По-умолчанию они могут быть положительными или отрицательными. Если выбрана опция UNSIGNED , то могут храниться только положительные числа.

MySQL поддерживает 5 типов целых чисел разных размеров и диапазонов:

Дробные числовые типы данных

Эти типы могут хранить дробные числа: FLOAT, DOUBLE и DECIMAL.

FLOAT занимает 4 байта, DOUBLE занимает 8 байт и аналогичен предыдущему. DOUBLE более точный.

DECIMAL(M,N) имеет изменяемую точность. M максимальное число цифр, N - число цифр после десятичной точки.

Например, DECIMAL(13,4) имеет 9 знаков до запятой и 4 после.

Строковые типы данных

По названию можно догадаться, что в них можно хранить строки.

CHAR(N) может хранить N символов и имеет фиксированную величину. Например, CHAR(50) должен всегда содержать 50 символов в каждой строке во всем столбце. Максимально возможное значениен 255 символов

VARCHAR(N) работает также, но диапазон может меняться. N - обозначает максимальное значение. Если хранимая строка короче N символов, то она будет занимать меньше места на жестком диске. Максимально возможное значениен 65535 символов.

Разновидности типа TEXT больше подходят для длинных строк. TEXT имеет ограничение в 65535 символов, MEDIUMTEXT в 16.7 миллионов, и LONGTEXT в 4.3 миллиарда символов. MySQL обычно хранит их в отдельных хранилищах на сервере, для того что бы главное хранилище было по возможности меньше и быстрее.

.

Заключение

Спазибо за чтение статьи. SQL - это важный язык и инструмент в арсенале веб-разработчика.

Ограничение PRIMARY KEY

PRIMARY KEY является ограничением целостности на уровне столбца - набор поддерживаемых правил, - которое формально отмечает столбец или группу столбцов как уникальный идентификатор для каждой строки в таблице.

Если вы пришли в Firebird из СУБД, которые поддерживают концепцию "первичного индекса" для определения ключа (обычно основанные на файлах системы, такие как Paradox, Access и MySQL), то Firebird и мир стандартов SQL вам понятны. Первичный ключ является не индексом, а ограничением. Одним из правил для такого ограничения является то, что ограничение должно иметь определенный уникальный индекс из одного или более связанных с ним непустых элементов.

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

ВНИМАНИЕ! Не надо импортировать существующий "первичный индекс" из наследуемой системы, основанной на файлах, или создавать такой индекс в ожидании объявления ограничения первичного ключа. Firebird не может накладывать ограничение первичного ключа поверх существующего индекса - по крайней мере в существующих версиях, включая 1.5, - а оптимизатор запросов не будет правильно работать при дублировании индексов.

Таблица может иметь только один первичный ключ. Когда вы определяете ограничение, Firebird автоматически создает требуемый индекс, используя множество именованных правил. Имена индексов первичных ключей обсуждаются далее.

ВНИМАНИЕ! Если вы конвертируете базу данных в Firebird из любого другого источника за исключением InterBase или Oracle, то вы должны обратить особое внимание на схему в отношении имен и ограничений первичного ключа.

Хотя само ограничение PRIMARY KEY не является ссылочным ограничением, оно обычно является обязательной частью любого ссылочного ограничения, будучи потенциальным объектом предложения REFERENCES ограничения FOREIGN KEY. Подробности см. в главе 17.

Выбор первичного ключа

Выявление столбцов в качестве кандидатов на первичный ключ выходит за рамки данного издания. Много прекрасных книг было написано о нормализации, процессе сокращения избыточности и повторяющихся групп в наборах данных, а также о правильной идентификации элемента, который уникальным образом представляет одну строку в таблице. Если вы новичок в реляционных базах данных, то затраты на изучение хорошей книги по моделированию данных не будут слишком большими.

Кандидат в первичные ключи, который может быть одним столбцом или группой столбцов, имеет два обязательных требования.

* Атрибут NOT NULL должен быть объявлен для всех столбцов в группе из одного или более столбцов. Целостность ключа может быть осуществлена только сравнением значений, a NULL не является значением.

* Столбец или группа столбцов должны быть уникальными - т. е. не может в таблице появиться более одной строки с теми же значениями. Например, номер водительских прав или социального обеспечения могут рассматриваться как кандидаты, потому что они генерируются системами, которые не допускают дубликатов номеров.

К этим теоретическим "установкам" должна быть добавлена третья.

* Общий размер кандидата в ключи должен быть 252 байта или меньше. Дело здесь не просто в подсчете символов. Этот лимит должен быть уменьшен - в некоторых случаях радикально - если присутствует несколько столбцов, недвоичная последовательность сортировки или многобайтовый набор символов.

Как реальные данные могут привести вас к неудаче

Используя таблицу EMPLOYEE базы данных employee.fdb из каталога /examples корневого каталога Firebird (employee.gdb в версии 1,0.x), давайте посмотрим, как реальные данные могут привести к ошибочности ваших теоретических предположений об уникальности. Вот объявление, которое показывает имеющие смысл данные, хранимые в этой таблице:

CREATE TABLE EMPLOYEE (

FIRST_NAME VARCHAR(15) NOT NULL,

/* предположение: служащий должен иметь имя */

LAST_NAME VARCHAR(20) NOT NULL,

/* предположение: служащий должен иметь фамилию */

PHONE_EXT VARCHAR(4),

HIRE_DATE DATE DEFAULT CURRENT_DATE NOT NULL,

DEPT_NO CHAR(3) NOT NULL,

JOB_CODE VARCHAR (5) NOT NULL,

JOB_GRADE SMALLINT NOT NULL,

JOB_COUNTRY VARCHAR(15) NOT NULL,

SALARY NUMERIC (15, 2) DEFAULT 0 NOT NULL,

FULL_NAME COMPUTED BY FIRST_NAME || || LAST_NAME) ;

Фактически эта структура не имеет кандидата в ключи. Невозможно идентифицировать одну строку служащего, используя (FIRST_NAME, LAST_NAME) в качестве ключа, поскольку комбинация двух элементов с вероятностью от средней до высокой может дублироваться в организации. Мы не сможем сохранить записи двух служащих с именем John Smith.

Для получения ключей необходимо что-то изобрести. Это "что-то" - механизм, известный как суррогатный ключ.

Суррогатные ключи

Мы уже рассматривали суррогатный ключ во вводной теме о ключах в главе 14. Суррогатный первичный ключ - значение, гарантирующее уникальность и не имеющее смыслового содержания, которое используется в качестве заменителя ключа в структуре таблицы, которая не может предоставить кандидата на ключ в собственной структуре. По этой причине в таблицу EMPLOYEE добавляется EMP_NO (объявляется через домен) для выполнения роли суррогатного ключа:

CREATE DOMAIN EMPNO SMALLINT ;

ALTER TABLE EMPLOYEE

ADD EMP_NO EMPNO NOT NULL,

ADD CONSTRAINT PK_EMPLOYEE

PRIMARY KEY(EMP_NO) ;

Эта база данных также содержит генератор с именем EMP_NO_GEN и триггер Before insert (перед добавлением) с именем SET_EMP_NO для таблицы EMPLOYEE для получения значения данного ключа в момент добавления новой строки. В разд. "Реализация автоинкрементных ключей" главы 31 эта техника описывается в деталях. Это рекомендованный способ реализации суррогатных ключей в Firebird.

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

Составные первичные ключи

В процессе анализа данных иногда в структуре данных можно отыскать единственный уникальный столбец. Теория советует найти два или более столбцов, сгруппированных вместе в качестве ключа, которые будут гарантировать уникальность строки. Когда множество столбцов объединяются для формирования ключа, такой ключ называется составным ключом (composite key) или иногда сложным ключом.

Если вы имеете опыт работы с такими СУБД, как Paradox, где использовали составные ключи для реализации иерархических отношений, вам, вероятно, будет тяжело расстаться с мыслью, что вам придется жить без них. Пока еще на практике составные ключи должны рассматриваться очень ограниченно в таких СУБД, как Firebird, где не выполняется проход по физическим индексным структурам на диске для реализации отношений.

В Firebird нет необходимости в составных индексах и, более того, составные индексы создают некоторые проблемы как для разработки, так и для производительности в случае больших таблиц.

* Составные ключи обычно являются составленными из неатомарных элементов ключа- т.е. выбранные столбцы имеют смысловое значение (они являются "значимыми данными") и, несомненно, уязвимы для внешних изменений и ошибок ручного ввода.

* Внешние ключи из других таблиц, которые ссылаются на эту таблицу, будут дублировать каждый элемент составного ключа. Ссылочная целостность подвергается риску при использовании неатомарных ключей. Комбинация неатомарных элементов увеличивает риск.

* Ключи - внешние, так же как и первичные - имеют постоянные индексы. Составные индексы имеют более строгие ограничения по размеру, чем индексы из одного столбца.

* Составные индексы имеют тенденцию к большим размерам. Большие индексы используют больше страниц базы данных, что приводит к тому, что индексные операции (сортировка, соединение и сравнение) выполняются медленнее, чем необходимо.

Атомарность столбцов первичного ключа

Рекомендуется на практике не включать в первичные и внешние ключи любые столбцы, имеющие смысл как данные. Это нарушает один из основных принципов проектирования реляционных баз данных- атомарность. Принцип атомарности требует, чтобы каждый элемент данных полностью существовал сам по себе с единым внутренним правилом управления его существованием.

Чтобы первичный ключ был атомарным, нужно быть вне человеческих решений. Если люди составляют его или классифицируют его, он не является атомарным. Если он является субъектом любого правила за исключением требований NOT NULL и уникальности, он не является атомарным. В приведенном ранее примере даже водительские права или номер социального обеспечения не соответствуют требованиям атомарности для первичного ключа, потому что они являются субъектами внешних систем.

Синтаксис объявления первичного ключа

Можно использовать несколько вариантов синтаксиса для назначения ограничения PRIMARY KEY столбцу или группе столбцов. Все столбцы, являющиеся элементами первичного ключа, должны быть предварительно определены с атрибутом NOT NULL. Так как нельзя добавить ограничение NOT NULL в столбец после его создания, необходимо позаботиться об этом ограничении до использования других ограничений.

Ограничение PRIMARY KEY может применяться в любой из следующих фаз создания метаданных:

* в определении столбца в операторах CREATE TABLE или ALTER TABLE как часть определения столбца;

* в определении таблицы в операторах CREATE TABLE или ALTER TABLE как отдельно определенное ограничение таблицы.

Определение первичного ключа как часть определения столбца

В следующей последовательности создается и подтверждается (commit) домен, не допускающий пустое значение, затем определяется столбец первичного ключа, основанный на этом домене, и одновременно применяется ограничение PRIMARY KEY к этому столбцу:

CREATE DOMAIN D_IDENTITY AS BIGINT NOT NULL;

CREATE TABLE PERSON (

PERSON_ID D_IDENTITY PRIMARY KEY,

Firebird создает ограничение таблицы с именем INTEG_M и индекс с именем RDB$PRIMARYnn. (пл в каждом случае - число, полученное от генератора. Эти два числа не связаны друг с другом.) Вы не можете повлиять на то, какими будут эти имена, и не можете поменять их.

Результат будет похожим, если вы используете тот же подход при добавлении столбца, используя оператор ALTER TABLE и создавая первичный ключ в одном предложении:

ALTER TABLE BOOK

ADD BOOK_ID D_IDENTITY PRIMARY KEY;

Определение первичного ключа как именованного ограничения

Другой способ определения первичного ключа в определении таблицы - добавить объявление ограничения в конце определений столбцов. Объявления ограничений помещаются последними, потому что они зависят от существования столбцов, к которым они обращаются. Этот метод дает вам возможность именования ограничений. Следующее объявление именует ограничение первичного ключа как PK_ATABLE:

CREATE TABLE ATABLE (

ID BIGINT NOT NULL,

ANOTHER_COLUMN VARCHAR (20),

CONSTRAINT PK_ATABLE PRIMARY KEY(ID));

Теперь вместо использования сгенерированного системой имени RDB$PRIMARYnnn Firebird использует PK_ATABLE В качестве имени этого ограничения. В Firebird 1.5 и выше он также применяет определенное пользователем имя ограничения для поддерживающего уникального индекса. В этом примере индекс получит имя PK_ATABLE, когда в других версиях его имя будет RDB$PRIMARYnnn.

Firebird 1.5 также позволяет использовать определенные пользователем имена для ограничения и поддерживающего его индекса.

Использование пользовательского индекса

До Firebird 1.5 не было возможности использовать убывающий индекс для поддержки первичного ключа. Начиная с версии 1.5, можно поддерживать первичный ключ убывающим индексом. Чтобы это сделать, в Firebird 1.5 добавляется расширение синтаксиса в форме предложения USING, позволяющего создавать индекс ASC (по возрастанию) или DESC (по убыванию) и присваивать ему имя, отличное от имени ограничения.

AS с и DESC определяют направление поиска. Подробнее эта концепция обсуждается в главе 18.

Следующий оператор создаст ограничение первичного ключа с именем PK ATEST и поддерживающий его убывающий индекс с именем IDX_PK_ATEST:

CREATE TABLE ATEST (

ID BIGINT NOT NULL,

DATA VARCHAR(10));

ALTER TABLE ATEST

ADD CONSTRAINT PK_ATEST PRIMARY KEY(ID)

USING DESC INDEX IDX_PK_ATEST;

Альтернативный синтаксис также будет работать:

CREATE TABLE ATEST (

ID BIGINT NOT NULL,

DATA VARCHAR(10),

CONSTRAINT PK_ATEST PRIMARY KEY(ID)

USING DESC INDEX IDX PK ATEST;

ВНИМАНИЕ! Если вы создаете индекс DESCENDING для ограничения первичного или уникального ключа, вы должны указать USING DESC INDEX для всех ссылающихся на него внешних ключей.

Добавление первичного ключа к существующей таблице

Добавление в таблицу ограничений может быть отложенным. Это общая практика разработчиков определять все свои таблицы без ограничений таблицы, а затем добавлять их, используя отдельный скрипт. Основная причина такой практики: большие скрипты часто дают сбой, потому что авторы забывают про некоторые зависимости. Просто будет меньше головной боли, если создавать базу данных в последовательности, которая уменьшает время и раздражение при исправлении ошибок зависимостей и нового запуска скриптов.

Обычно в первом скрипте мы объявляем таблицы и подтверждаем их создание:

CREATE TABLE ATABLE (

ID BIGINT NOT NULL,

ANOTHER_COLUMN VARCHAR (20),

< другие столбцы >) ;

CREATE TABLE ANOTHERTABLE (

ALTER TABLE ATABLE

ADD CONSTRAINT PK_ATABLE

PRIMARY KEY(ID);

ALTER TABLE ANOTHERTABLE...

В следующей главе при рассмотрении определений FOREIGN KEY станут очевидными преимущества создания базы данных в последовательности надежных зависимостей.

Из книги Базы данных: конспект лекций автора Автор неизвестен

3. Ограничение целостности по состоянию Ограничение целостности реляционного объекта данных по состоянию – это так называемый инвариант данных.При этом целостность следует уверенно отличать от безопасности, которая, в свою очередь, подразумевает защиту данных от

Из книги Язык программирования С# 2005 и платформа.NET 2.0. автора Троелсен Эндрю

Ограничение использования атрибута По умолчанию пользовательские атрибуты могут применяться к любой части программного кода (к методам, классам, свойствам и т.д.). Поэтому, если только это имеет смысл, можно использовать VehicleDescription для определения (среди прочего) методов,

Из книги Linux-сервер своими руками автора

11.2.2. Ограничение доступа Я считаю необходимым подробно рассмотреть блочную директиву Limit. Эта директива определяет вид и параметры доступа к тому или иному каталогу. Рассмотрим листинг 11.9.Листинг 11.9. Пример использования директивы Limit

Из книги Основы объектно-ориентированного программирования автора Мейер Бертран

Из книги Программирование на языке Пролог для искусственного интеллекта автора Братко Иван

Ограничение доступа клиентам Для ограничения доступа клиентов к некоторой компоненте h, будет использована возможность включения в объявление класса двух или более разделов feature. Объявление будет выглядеть следующим образомclass S2 featuref ...g ...feature {A, B}h ......endКомпоненты f и g

Из книги Удвоение продаж в интернет-магазине автора Парабеллум Андрей Алексеевич

5.1. Ограничение перебора В процессе достижения цели пролог-система осуществляет автоматический перебор вариантов, делая возврат при неуспехе какого-либо из них. Такой перебор - полезный программный механизм, поскольку он освобождает пользователя от необходимости

Из книги Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ автора Борри Хелен

Ограничение Второй элемент формулы ОДП – дедлайн (от англ. deadline), или ограничение. Это может быть ограничение по времени (например, скидка 50 % только два дня) или по количеству (например, ценный подарок для первых 50 покупателей). Причем короткие по времени дедлайны работают

Из книги Omert@. Руководство по компьютерной безопасности и защите информации для Больших Боссов автора Экслер Алекс

Ссылочное ограничение Ссылочное ограничение реализовано как FOREIGN KEY. Ограничение внешнего ключа существует только в контексте другой таблицы и уникального ключа этой таблицы, заданного явно или неявно в предложении REFERENCES при объявлении ограничения.Таблицы, связанные в

Из книги Linux глазами хакера автора Флёнов Михаил Евгеньевич

Ограничение NOT NULL Firebird не поддерживает атрибут указания допустимости пустого значения, как это делают некоторые нестандартные СУБД. В соответствии со стандартами все столбцы в Firebird могут содержать пустое значение, если не будет явно указано ограничение NOT NULL.

Из книги Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/FireBird/Yaffil автора Ковязин Алексей Николаевич

Из книги Анонимность и безопасность в Интернете. От «чайника» к пользователю автора Колисниченко Денис Николаевич

Из книги автора

4.11.5. Ограничение сети В крупных сетях описывать каждый компьютер очень сложно. Для облегчения этой задачи можно использовать групповые записи. Например, вам надо разрешить выход в Интернет только для сети 192.168.1.x (с маской 255.255.255.0). Это значит, что первые 24 бита (первые три

Из книги автора

9.5.8. Ограничение канала При организации доступа в Интернет очень часто требуется отдельным пользователям обеспечить большую скорость подключения. Как это сделать, когда по умолчанию все равноправны и могут работать на максимально доступной на данный момент скорости?

Из книги автора

Ограничение CHECK Одним из наиболее полезных ограничений в базе данных является ограничение проверки. Идея его очень проста - проверять вставляемое в таблицу значение на какое-либо условие и, в зависимости от выполнения условия, вставлять или не вставлять данные.Синтаксис

Из книги автора

П2.4. Ограничение доступа П2.4.1. Запрет доступа к сайту (или к списку сайтов) Предположим, что вам нужно запретить доступ к определенному сайту (или к списку сайтов). Для этого зайдите в раздел Биллинг | Клиенты | Фильтры | До группы (рис. П2.10). Выполните команду меню Действие |

Из книги автора

П2.4.2. Ограничение скорости Для ограничения скорости работы того или иного пользователя выделите его в списке пользователей, нажмите правую кнопку мыши и выберите команду Свойства. Перейдите на вкладку Ограничения (рис. П2.14), снимите флажок По умолчанию в области

В этой статье мы попробуем рассмотреть все, что касается ключей в SQL: для чего нужны, создание, ограничения ключей. В общем: будет скучно 😉

План на сегодня такой:

В теории реляционных баз данных — ключи это некие сущности, созданы для установления определенных ограничений, которые поддерживают целостность и доступность данных в таблицах баз данных.

Если говорить простыми словами, то ключи в sql созданы для того, чтобы указать дополнительную функциональность столбца. Будь то уникальность или то, что столбец ссылается на другую таблицу (внешний ключ).

Первичный ключ

Столбец, который в базе данных должен быть уникальным помечают первичным ключом. Первичный ключ или primary key означает, что в таблице значение колонки primary key не может повторяться. Таким образом данный ключ позволяет однозначно идентифицировать запись в таблице не боясь при этом, что значение столбца повториться. Сразу пример: допустим у Вас есть таблица пользователей. В данной таблице есть поля: ФИО, год рождения, телефон. Как идентифицировать пользователя? Таким параметрам как ФИО и телефон доверять нельзя. Ведь у нас может быть несколько пользователей не только с одинаковой фамилией, но и с именем. Телефон может меняться со временем и пользователь с номером телефона может оказаться не тем кто у нас в базе данных.

Вот для этого и придумали первичный ключ. Один раз присвоили уникальный идентификатор и все. В mySql на примере которой мы выполняем все примеры из поле AUTO_INCREMENT нельзя задать если не указать, что это первичный ключ.

Думаю, что не стоит упоминать, что поле помеченное как первичный ключ не может быть пустым при создании записи.

Внешний ключ (foreign key )

Есть еще внешний ключ (foreign key ). Его еще называют ссылочным. Он нужен для связывания таблиц между собой.

Если посмотреть на картинку выше, то внешним ключем будет поле поставщик в таблице обувь. Как правило, при создании таблицы задают колонку уникальных целочисленных значений. Как мы это делали когда создавали таблицу supplier.

Колонка supplier_id будет уникальна для каждой записи. Ее значение и будет выступать на мести колонки поставщик в таблице обувь. Предлагаю сразу и рассмотреть на примере как создается внешний ключ.

Создание внешнего ключа

create table shoes(shoes_id int auto_increment primary key, title text, size int, price float, count int, type varchar(30), supplier int, foreign key (supplier) references supplier (supplier_id));

Как видно на примере выше, синтаксис по созданию внешнего ключа довольно прост. Нужно в таблицу добавить поле, а после объявить это поле как внешний ключ и указать, куда он будет ссылаться. В данном случае поле supplier будет ссылаться на поле supplier_id в таблице supplier.

Составной ключ (composite key)

Что касается составного ключа — это несколько первичных ключей в таблице. Таким образом, создав composite key , уникальность записи будет проверяться по полям, которые объединенные в этот ключ.

Бывают ситуации, когда при вставке в таблицу нужно проверять запись на уникальность сразу по нескольким полям. Вот для этого и придуман составной ключ. Для примера я создам простую таблицу с composite key , чтобы показать синтаксис:

Create table test(field_1 int, field_2 text, field_3 bigint, primary key (field_1, field_3));

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

Это все, что касается ключей в SQL. Это небольшое пособие — подготовка к статье где мы подробно рассмотрим как объединять таблицы, чтобы они составляли единую базу данных.

PRIMARY KEY — первичный ключ, ограничение, позволяющее однозначно идентифицировать каждую запись в таблице SQL .

PRIMARY KEY Oracle
Первичный Ключ (PRIMARY KEY ) может ограничивать таблицы или их столбцы. Это ограничение работает так же как и ограничение UNIQUE. Но следует учитывать различие между первичными ключами и уникальностью столбцов в способе их использования с внешними ключами. Первичные ключи не могут позволять значений NULL. Это означает что, подобно полям в ограничении UNIQUE, любое поле, используемое в ограничении PRIMARY KEY , должно уже быть обьявлено NOT NULL.

PRIMARY KEY Oracle . Пример №1.
Пример создания таблицы SQL с ограничением PRIMARY KEY :

Student
(Kod_stud integer NOT NULL PRIMARY KEY ,
Fam char(30) NOT NULL UNIQUE,
Adres char(50),
Ball decimal);

Лучше всего помещать ограничение PRIMARY KEY в поле (или в поля), которое будет образовывать уникальный идентификатор строки, и сохранить ограничение UNIQUE для полей которые должны быть уникальными логически (такие как номера телефона или поле sname), а не для идентификации строк. Ограничение PRIMARY KEY может также быть применено для многочисленных полей, составляющих уникальную комбинацию значений:

PRIMARY KEY Oracle . Пример №2.

CREATE TABLE Student
(Fam char (30) NOT NULL,
Im char (30) NOT NULL
Adres char (50),
PRIMARY KEY (Fam, Im));

PRIMARY KEY MySQL

PRIMARY KEY SQL / MySQL . Пример №3.

CREATE TABLE Persons (
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
PRIMARY KEY (P_Id));

PRIMARY KEY SQL / MySQL . Пример №4.

CREATE TABLE `ad_packages` (
`id` int(111) NOT NULL auto_increment,
`title` varchar(132) NOT NULL default »,
`price` float NOT NULL default ‘0’,
`type` varchar(22) NOT NULL default »,
`c_type` enum(‘cash’,’points’,’rur’) NOT NULL default ‘cash’,
PRIMARY KEY (`id`)
);

PRIMARY KEY SQL / MySQL . Пример №5.

CREATE TABLE `gamestat` (
`id` int(11) NOT NULL auto_increment,
`game` varchar(10) NOT NULL default ‘tuz’,
`stavok` int(11) NOT NULL default ‘0’,
`usd` float NOT NULL default ‘0’,
`rur` float NOT NULL default ‘0’,
`point` float NOT NULL default ‘0’,
`bank_usd` decimal(12,2) NOT NULL default ‘0.00’,
`bank_rur` decimal(12,2) NOT NULL default ‘0.00’,
`bank_point` decimal(12,2) NOT NULL default ‘0.00’,
PRIMARY KEY (`id`)
);

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

Для решения подобных задач SQL позволяет вам определять ограничения для столбцов и таблиц. Ограничения дают вам возможность управлять данными в таблицах так, как вы захотите. Если пользователь попытается сохранить в столбце значение, нарушающее ограничения, возникнет ошибка. Ограничения будут действовать, даже если это значение по умолчанию.

5.3.1. Ограничения-проверки

Ограничение-проверка - наиболее общий тип ограничений. В его определении вы можете указать, что значение данного столбца должно удовлетворять логическому выражению (проверке истинности). Например, цену товара можно ограничить положительными значениями так:

Name text, price numeric CHECK (price > 0) );

Как вы видите, ограничение определяется после типа данных, как и значение по умолчанию. Значения по умолчанию и ограничения могут указываться в любом порядке. Ограничение-проверка состоит из ключевого слова CHECK , за которым идёт выражение в скобках. Это выражение должно включать столбец, для которого задаётся ограничение, иначе оно не имеет большого смысла.

Вы можете также присвоить ограничению отдельное имя. Это улучшит сообщения об ошибках и позволит вам ссылаться на это ограничение, когда вам понадобится изменить его. Сделать это можно так:

CONSTRAINT positive_price CHECK (price > 0));

То есть, чтобы создать именованное ограничение, напишите ключевое слово CONSTRAINT , а за ним идентификатор и собственно определение ограничения. (Если вы не определите имя ограничения таким образом, система выберет для него имя за вас.)

Ограничение-проверка может также ссылаться на несколько столбцов. Например, если вы храните обычную цену и цену со скидкой, так вы можете гарантировать, что цена со скидкой будет всегда меньше обычной:

CREATE TABLE products (product_no integer, name text, price numeric CHECK (price > 0), discounted_price numeric CHECK (discounted_price > 0), CHECK (price > discounted_price) );

Первые два ограничения определяются похожим образом, но для третьего используется новый синтаксис. Оно не связано с определённым столбцом, а представлено отдельным элементом в списке. Определения столбцов и такие определения ограничений можно переставлять в произвольном порядке.

Про первые два ограничения можно сказать, что это ограничения столбцов, тогда как третье является ограничением таблицы, так как оно написано отдельно от определений столбцов. Ограничения столбцов также можно записать в виде ограничений таблицы, тогда как обратное не всегда возможно, так как подразумевается, что ограничение столбца ссылается только на связанный столбец. (Хотя Postgres Pro этого не требует, но для совместимости с другими СУБД лучше следовать это правилу.) Ранее приведённый пример можно переписать и так:

CREATE TABLE products (product_no integer, name text, price numeric, CHECK (price > 0), discounted_price numeric, CHECK (discounted_price > 0), CHECK (price > discounted_price));

Или даже так:

CREATE TABLE products (product_no integer, name text, price numeric CHECK (price > 0), discounted_price numeric, CHECK (discounted_price > 0 AND price > discounted_price));

Это дело вкуса.

Ограничениям таблицы можно присваивать имена так же, как и ограничениям столбцов:

CREATE TABLE products (product_no integer, name text, price numeric, CHECK (price > 0), discounted_price numeric, CHECK (discounted_price > 0), CONSTRAINT valid_discount CHECK (price > discounted_price));

Следует заметить, что ограничение-проверка удовлетворяется, если выражение принимает значение true или NULL. Так как результатом многих выражений с операндами NULL будет значение NULL, такие ограничения не будут препятствовать записи NULL в связанные столбцы. Чтобы гарантировать, что столбец не содержит значения NULL, можно использовать ограничение NOT NULL, описанное в следующем разделе.

5.3.2. Ограничения NOT NULL

Ограничение NOT NULL просто указывает, что столбцу нельзя присваивать значение NULL. Пример синтаксиса:

CREATE TABLE products (product_no integer NOT NULL , name text NOT NULL , price numeric);

Ограничение NOT NULL всегда записывается как ограничение столбца и функционально эквивалентно ограничению CHECK ( имя_столбца IS NOT NULL) , но в Postgres Pro явное ограничение NOT NULL работает более эффективно. Хотя у такой записи есть недостаток - назначить имя таким ограничениям нельзя.

Естественно, для столбца можно определить больше одного ограничения. Для этого их нужно просто указать одно за другим:

CREATE TABLE products (product_no integer NOT NULL, name text NOT NULL, price numeric NOT NULL CHECK (price > 0));

Порядок здесь не имеет значения, он не обязательно соответствует порядку проверки ограничений.

Для ограничения NOT NULL есть и обратное: ограничение NULL . Оно не означает, что столбец должен иметь только значение NULL, что конечно было бы бессмысленно. Суть же его в простом указании, что столбец может иметь значение NULL (это поведение по умолчанию). Ограничение NULL отсутствует в стандарте SQL и использовать его в переносимых приложениях не следует. (Оно было добавлено в Postgres Pro только для совместимости с некоторыми другими СУБД.) Однако некоторые пользователи любят его использовать, так как оно позволяет легко переключать ограничения в скрипте. Например, вы можете начать с:

CREATE TABLE products (product_no integer NULL, name text NULL, price numeric NULL);

и затем вставить ключевое слово NOT , где потребуется.

Подсказка

При проектировании баз данных чаще всего большинство столбцов должны быть помечены как NOT NULL.

5.3.3. Ограничения уникальности

Ограничения уникальности гарантируют, что данные в определённом столбце или группе столбцов уникальны среди всех строк таблицы. Ограничение записывается так:

CREATE TABLE products (product_no integer UNIQUE

в виде ограничения столбца и так:

CREATE TABLE products (product_no integer, name text, price numeric, UNIQUE (product_no) );

в виде ограничения таблицы.

Чтобы определить ограничение уникальности для группы столбцов, запишите его в виде ограничения таблицы, перечислив имена столбцов через запятую:

UNIQUE (a, c) );

Такое ограничение указывает, что сочетание значений перечисленных столбцов должно быть уникально во всей таблице, тогда как значения каждого столбца по отдельности не должны быть (и обычно не будут) уникальными.

Вы можете назначить уникальному ограничению имя обычным образом:

CREATE TABLE products (product_no integer CONSTRAINT must_be_different UNIQUE, name text, price numeric);

При добавлении ограничения уникальности будет автоматически создан уникальный индекс-B-дерево для столбца или группы столбцов, перечисленных в ограничении. Условие уникальности, распространяющееся только на некоторые строки, нельзя записать в виде ограничения уникальности, однако такое условие можно установить, создав уникальный частичный индекс .

Вообще говоря, ограничение уникальности нарушается, если в таблице оказывается несколько строк, у которых совпадают значения всех столбцов, включённых в ограничение. Однако два значения NULL при сравнении никогда не считаются равными. Это означает, что даже при наличии ограничения уникальности в таблице можно сохранить строки с дублирующимися значениями, если они содержат NULL в одном или нескольких столбцах ограничения. Это поведение соответствует стандарту SQL, но мы слышали о СУБД, которые ведут себя по-другому. Имейте в виду эту особенность, разрабатывая переносимые приложения.

5.3.4. Первичные ключи

Ограничение первичного ключа означает, что образующий его столбец или группа столбцов может быть уникальным идентификатором строк в таблице. Для этого требуется, чтобы значения были одновременно уникальными и отличными от NULL. Таким образом, таблицы со следующими двумя определениями будут принимать одинаковые данные:

CREATE TABLE products (product_no integer UNIQUE NOT NULL, name text, price numeric); CREATE TABLE products (product_no integer PRIMARY KEY , name text, price numeric);

Первичные ключи могут включать несколько столбцов; синтаксис похож на запись ограничений уникальности:

CREATE TABLE example (a integer, b integer, c integer, PRIMARY KEY (a, c) );

При добавлении первичного ключа автоматически создаётся уникальный индекс-B-дерево для столбца или группы столбцов, перечисленных в первичном ключе, и данные столбцы помечаются как NOT NULL .

Таблица может иметь максимум один первичный ключ. (Ограничений уникальности и ограничений NOT NULL, которые функционально почти равнозначны первичным ключам, может быть сколько угодно, но назначить ограничением первичного ключа можно только одно.) Теория реляционных баз данных говорит, что первичный ключ должен быть в каждой таблице. В Postgres Pro такого жёсткого требования нет, но обычно лучше ему следовать.

Первичные ключи полезны и для документирования, и для клиентских приложений. Например, графическому приложению с возможностями редактирования содержимого таблицы, вероятно, потребуется знать первичный ключ таблицы, чтобы однозначно идентифицировать её строки. Первичные ключи находят и другое применение в СУБД; в частности, первичный ключ в таблице определяет целевые столбцы по умолчанию для сторонних ключей, ссылающихся на эту таблицу.

5.3.5. Внешние ключи

Ограничение внешнего ключа указывает, что значения столбца (или группы столбцов) должны соответствовать значениям в некоторой строке другой таблицы. Это называется ссылочной целостностью двух связанных таблиц.

Пусть у вас уже есть таблица продуктов, которую мы неоднократно использовали ранее:

CREATE TABLE products (product_no integer PRIMARY KEY, name text, price numeric);

Давайте предположим, что у вас есть таблица с заказами этих продуктов. Мы хотим, чтобы в таблице заказов содержались только заказы действительно существующих продуктов. Поэтому мы определим в ней ограничение внешнего ключа, ссылающееся на таблицу продуктов:

REFERENCES products (product_no) , quantity integer);

С таким ограничением создать заказ со значением product_no , отсутствующим в таблице products (и не равным NULL), будет невозможно.

В такой схеме таблицу orders называют подчинённой таблицей, а products - главной . Соответственно, столбцы называют так же подчинённым и главным (или ссылающимся и целевым).

Предыдущую команду можно сократить так:

CREATE TABLE orders (order_id integer PRIMARY KEY, product_no integer REFERENCES products , quantity integer);

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

Внешний ключ также может ссылаться на группу столбцов. В этом случае его нужно записать в виде обычного ограничения таблицы. Например:

CREATE TABLE t1 (a integer PRIMARY KEY, b integer, c integer, FOREIGN KEY (b, c) REFERENCES other_table (c1, c2) );

Естественно, число и типы столбцов в ограничении должны соответствовать числу и типам целевых столбцов.

Ограничению внешнего ключа можно назначить имя стандартным способом.

Таблица может содержать несколько ограничений внешнего ключа. Это полезно для связи таблиц в отношении многие-ко-многим. Скажем, у вас есть таблицы продуктов и заказов, но вы хотите, чтобы один заказ мог содержать несколько продуктов (что невозможно в предыдущей схеме). Для этого вы можете использовать такую схему:

CREATE TABLE products (product_no integer PRIMARY KEY, name text, price numeric); CREATE TABLE orders (order_id integer PRIMARY KEY, shipping_address text, ...); CREATE TABLE order_items (product_no integer REFERENCES products, order_id integer REFERENCES orders, quantity integer, PRIMARY KEY (product_no, order_id));

Заметьте, что в последней таблице первичный ключ покрывает внешние ключи.

Мы знаем, что внешние ключи запрещают создание заказов, не относящихся ни к одному продукту. Но что делать, если после создания заказов с определённым продуктом мы захотим удалить его? SQL справится с этой ситуацией. Интуиция подсказывает следующие варианты поведения:

    Запретить удаление продукта

    Удалить также связанные заказы

    Что-то ещё?

Для иллюстрации давайте реализуем следующее поведение в вышеприведённом примере: при попытке удаления продукта, на который ссылаются заказы (через таблицу order_items), мы запрещаем эту операцию. Если же кто-то попытается удалить заказ, то удалится и его содержимое:

CREATE TABLE products (product_no integer PRIMARY KEY, name text, price numeric); CREATE TABLE orders (order_id integer PRIMARY KEY, shipping_address text, ...); CREATE TABLE order_items (product_no integer REFERENCES products ON DELETE RESTRICT , order_id integer REFERENCES orders ON DELETE CASCADE , quantity integer, PRIMARY KEY (product_no, order_id));

Ограничивающие и каскадные удаления - два наиболее распространённых варианта. RESTRICT предотвращает удаление связанной строки. NO ACTION означает, что если зависимые строки продолжают существовать при проверке ограничения, возникает ошибка (это поведение по умолчанию). (Главным отличием этих двух вариантов является то, что NO ACTION позволяет отложить проверку в процессе транзакции, а RESTRICT - нет.) CASCADE указывает, что при удалении связанных строк зависимые от них будут так же автоматически удалены. Есть ещё два варианта: SET NULL и SET DEFAULT . При удалении связанных строк они назначают зависимым столбцам в подчинённой таблице значения NULL или значения по умолчанию, соответственно. Заметьте, что это не будет основанием для нарушения ограничений. Например, если в качестве действия задано SET DEFAULT , но значение по умолчанию не удовлетворяет ограничению внешнего ключа, операция закончится ошибкой.

Аналогично указанию ON DELETE существует ON UPDATE , которое срабатывает при изменении заданного столбца. При этом возможные действия те же, а CASCADE в данном случае означает, что изменённые значения связанных столбцов будут скопированы в зависимые строки.

Обычно зависимая строка не должна удовлетворять ограничению внешнего ключа, если один из связанных столбцов содержит NULL. Если в объявление внешнего ключа добавлено MATCH FULL , строка будет удовлетворять ограничению, только если все связанные столбцы равны NULL (то есть при разных значениях (NULL и не NULL) гарантируется невыполнение ограничения MATCH FULL). Если вы хотите, чтобы зависимые строки не могли избежать и этого ограничения, объявите связанные столбцы как NOT NULL .

Внешний ключ должен ссылаться на столбцы, образующие первичный ключ или ограничение уникальности. Таким образом, для связанных столбцов всегда будет существовать индекс (определённый соответствующим первичным ключом или ограничением), а значит проверки соответствия связанной строки будут выполняться эффективно. Так как команды DELETE для строк главной таблицы или UPDATE для зависимых столбцов потребуют просканировать подчинённую таблицу и найти строки, ссылающиеся на старые значения, полезно будет иметь индекс и для подчинённых столбцов. Но это нужно не всегда, и создать соответствующий индекс можно по-разному, поэтому объявление внешнего ключа не создаёт автоматически индекс по связанным столбцам.



Статьи по теме