Современная структура языка.
Существуют различные подходы к структурированию языка SQL, но мы воспользуемся традиционным. Как уже отмечалось ранее, в языках для работы с данными выделяют три части – язык определения данных (DDL), язык манипулирования данными (DML) и язык управления данными (DCL). Эти три части имеются и в языке SQL.
К языку определения данных в первую очередь относятся запросы, предназначенные для создания (CREATE), изменения (ALTER) и удаления (DROP) таблиц. Помимо таблиц, в базе данных немало и других сущностей, которые также можно создавать, изменять и удалять, но мы, в рамках данного конспекта, остановимся только на работе с таблицами. Этого достаточно, чтобы выполнять основные операции.
Язык манипулирования данными включает запросы на добавление (INSERT), изменение (UPDATE) и удаление (DELETE) записей. Кроме того, сюда же относятся и запросы на выборку данных (SELECT).
Наконец, говоря о языке управления данными, нужно в первую очередь упомянуть запросы для создания ролей (CREATE ROLE), а также назначения (GRANT) и отзыва (REVOKE) полномочий. Не все СУБД вообще поддерживают эти запросы, а во многих СУБД эти же действия можно выполнить, используя графические средства администрирования. В настоящем конспекте мы не будет рассматривать эту часть языка, а интересующиеся могут обратиться к литературе или непосредственно к стандарту.
|
|
Мы перечислили основные запросы, требующиеся в повседневной работе, так что можно перейти к их более подробному рассмотрению.
Как уже было сказано, мы рассмотрим конструкции языка, использующиеся для работы с таблицами.
Для создания таблиц используется запрос CREATE TABLE. Мы не будем углубляться в подробности, а ограничимся базовыми частями этого запроса. Его структура выглядит следующим образом:
CREATE TABLE имя_таблицы
(имя_поля1 тип_поля [(размер)] [ограничение_поля],
….
имя_поляN тип_поля [(размер)] [ограничение_поля],
[ограничения_таблицы]);
Приведем пример запроса и разберем его части. Предположим, что нам нужно создать таблицу для хранения данных о студентах, в которой планируем хранить сведения о номере зачетной книжки, фамилии, имени и отчестве, дате рождения, серии и номере паспорта, номере аттестата о среднем образовании, родном городе, а также шифре группы, в которой он учится. Кроме того, необходимо установить связь с группой. Запрос будет выглядеть следующим образом (названия полей, для простоты, приведены на русском языке, нужно иметь в виду, что не все СУБД это позволяют):
CREATE TABLE Студент
(НомерЗачетки CHAR(10) PRIMARY KEY,
Имя VARCHAR(25) NOT NULL,
Отчество VARCHAR(25) NOT NULL,
Фамилия VARCHAR(25) NOT NULL,
ДатаРождения DATE NOT NULL,
|
|
СерияПаспорта CHAR(4) NOT NULL,
НомерПаспорта CHAR(6) NOT NULL,
Аттестат VARCHAR(20) NOT NULL UNIQUE,
РоднойГород VARCHAR(50) NOT NULL DEFAULT ‘Киров’,
ШифрГруппы VARCHAR(10),
UNIQUE (СерияПаспорта, НомерПаспорта),
CONSTRAINT Студент_Группа FOREIGN KEY (ШифрГруппы)
REFERENCES Группа (ШифрГруппы)
ON UPDATE CASCADE ON DELETE SET NULL);
Теперь прокомментируем запрос. Первое поле таблицы, НомерЗачетки, в качестве типа использует строку постоянной длины (предположим, что номера зачетных книжек состоят из 10 символов), а также к нему применено ограничение PRIMARY KEY, что в переводе означает первичный ключ. С помощью этого ограничения мы можем определить первичный ключ таблицы. Надо иметь в виду, что если первичный ключ составной, то следует задавать ограничение не для отдельных строк, а для таблицы в целом, как это будет рассмотрено немного далее.
Поля Имя, Отчество и Фамилия – это строки переменной длины (то есть, хранятся только введенные символы, но не более заданного размера), и кроме того, для них задано ограничение NOT NULL. Это ограничение означает запрет пустых значений в этих полях. В самом деле, у каждого человека должно быть имя, отчество и фамилия (по крайней мере, мы так предполагаем). Соответственно, СУБД будет отслеживать заполненность этих полей значениями. Надо помнить, что NULL означает отсутствие значения, и NULL не эквивалентно пустой строке или строке из одних пробелов – это уже определенные значения. Об этом нужно помнить, и мы еще вернемся к этому вопросу при рассмотрении запросов на выборку данных.
Поля ДатаРождения, СерияПаспорта и НомерПаспорта не представляют особого интереса. Обратим внимание на поле Аттестат. Для него, помимо запрета пустых значений, задано ограничение UNIQUE. Оно означает требования уникальности значений в этом поле. То есть, номера аттестатов у наших студентов не могут повторяться. При попытке добавить строку, номер аттестата в которой совпадает с уже имеющимся, мы получим ошибку и строка добавлена не будет.
Следующее поле, РоднойГород, снабжено значением по умолчанию при помощи конструкции DEFAULT. В нашем случае мы предполагаем, что большинство студентов будет местными, то есть если город в явном виде задан не будет, то будет устанавливаться значение по умолчанию – Киров.
Последнее поле ШифрГруппы – это поле внешнего ключа, с его помощью мы сможем установить связь студента и группы, в которой он учится. Обратите внимание, что для данного поля мы не установили ограничения NOT NULL, так как студент в какие-то моменты времени может и не входить ни в одну группу. В случае, если бы такое ограничение было задано, мы не смогли бы внести данные о студенте без помещения его в конкретную группу, а это не всегда удобно.
Мы рассмотрели все поля и основные ограничения, которые могут применяться к отдельному полю. Теперь перейдем к ограничениям, задаваемым для таблицы. В нашем примере первым стоит ограничение UNIQUE, которое требует уникальности значений сразу двух полей – серии и номера паспорта. То есть, серии и номера по отдельности могут повторяться, но вот их сочетания должны быть уникальны, как это и обстоит в действительности. Аналогично задается ограничение первичного ключа, если в него входят несколько полей. Данное ограничение мы записали в сокращенной форме.
Для записи следующего ограничения использован более полный синтаксис. Запись начинается с ключевого слова CONSTRAINT, что в переводе и означает «ограничение». Далее идет имя ограничения, с помощью которого можно к нему обращаться, скажем, при необходимости его удалить (в запросе на изменение таблицы). После имени указывается тип ограничения, в нашем случае это ограничение внешнего ключа, FOREIGN KEY, а затем уже идут параметры самого ограничения. Для внешнего ключа мы сначала указываем, какое поле (или поля) в нашей таблице используется для связи, затем, после ключевого слова REFERENCES (англ. «ссылается») указываем таблицу и список полей, которые используются для связи в ней. В большинстве случаев это поля первичного ключа. Наконец, после указания полей, мы можем задать поведение нашей таблицы при изменении значения первичного ключа в главной таблице. Ключевое слово ON UPDATE задает поведение при изменении первичного ключа, в нашем случае это CASCADE, то есть каскадное обновление. При изменении шифра группы в таблице групп все записи студентов, связанных с этой группой, также будут обновлены и им будет задано новое значение внешнего ключа. Ключевое слово ON DELETE определяет поведение студентов при удалении группы, в которую они входят. Очевидно, что студенты не должны никуда исчезать, поэтому каскадное удаление тут не подходит. В то же время, задать новое значение шифра группы также невозможно – оно просто неизвестно в этот момент. Поэтому выбран вариант SET NULL – установка пустого значения. Соответственно, после удаления группы студенты, которые в ней числились, перестают входить в какую-либо группу.
|
|
Мы рассмотрели основные элементы запроса создания таблицы. Теперь можно обсудить запрос на изменение таблицы. Он выглядит следующим образом:
ALTER TABLE имя_таблицы
[ADD [COLUMN] имя_поля тип_поля [(размер)] [ограничения_поля]]
| [ALTER [COLUMN] имя_поля SET DEFAULT значение]
| [ALTER [COLUMN] имя_поля DROP DEFAULT]
| [ALTER [COLUMN] имя_поля ADD SCOPE имя_таблицы]
| [ALTER [COLUMN] имя_поля DROP SCOPE {RESTRICT | CASCADE}]
| [DROP [COLUMN] имя_поля {RESTRICT | CASCADE}]
| [ADD ограничение_таблицы]
| [DROP CONSTRAINT ограничение_таблицы {RESTRICT | CASCADE}];
В принципе, по тексту запроса в целом видны его возможности. Мы может добавить/удалить колонку таблицы, установить/убрать значение по умолчанию, добавить/удалить ограничение на таблицу.
Предложения ADD SCOPE и DROP SCOPE используются для определения пользовательских типов данных. В настоящем конспекте мы не затрагиваем эту тему, интересующиеся могут обратиться к литературе.
Ключевые слова RESTRICT и CASCADE определяют поведение СУБД, если у удаляемой колонки таблицы, области определения или ограничения имеются зависимые элементы. Использование RESTRICT приведет к тому, что операция удаления будет отменена, если найдутся зависимые элементы, а при использовании CASCADE зависимые элементы будут также удалены. Приведем небольшой пример, удалим значение по умолчанию для поля РоднойГород таблицы Студент.
|
|
ALTER TABLE Студент
ALTER COLUMN РоднойГород DROP DEFAULT;
В целом формирование таких запросов не должно представлять особых сложностей.
Для удаления таблицы используется запрос DROP TABLE, который выглядит следующим образом:
DROP TABLE имя_таблицы {RESTRICT | CASCADE}
Ключевые слова RESTRICT и CASCADE имеют здесь тот же смысл, что и в запросе на изменение таблицы.
На этом мы закончим рассмотрение языка определения данных. Мы не затрагивали особенности реализации запросов в конкретных СУБД, эта тема выходит за рамки данного конспекта. Тем не менее, приведенные в качестве примера запросы должны успешно сработать в большинстве популярных систем.