\chapter{ \label{p2} Введение в язык SQL}

Язык SQL был разработан фирмой IBM в конце 1970-х годов и был
принят Американским национальным институтом стандартов (ANSI) в
качестве национального стандарта США в 1992 году~\cite{kre2005}.

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

С помощью SQL можно определять структуры базы данных, а также
запрашивать и обновлять информацию в базе данных. Совокупность
команд, служащих для определения данных, называют иногда
\emph{языком определения данных} (data definition language, DDL),
а совокупность команд для обновления и запроса данных ---
\emph{языком манипулирования данными} (data manipulation language,
DML). Далее в учебном пособии будут рассмотрены оба эти
подмножества языка SQL на примере, приведенном в предыдущей главе.

\section{Средства определения данных языка SQL}

\noindent
{\large \bf{Оператор CREATE TABLE}}

\vspace{0.2cm}

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

\li\label{sql_create}
\verbatimtabinput[4]{list_2_1.sql}



В SQL имеется пять типов ограничений: PRIMARY KEY, NULL/NOT NULL, UNIQUE, FOREIGN KEY и CHECK. 
В листинге~\ref{sql_create} столбец CustomerID принадлежит к типу данных Integer (целочисленный) и 
имеет свойство Primary Key. Следующий столбец, Name, имеет тип данных Character (строковый) 
с максимальной длиной 25 символов. Ключевые слова Not Null означают, что этот столбец обязан
иметь значение.

В SQL первичные ключи ни при каких условиях не могут иметь пустых значений. Именно поэтому для столбца CustomerID можно просто указать свойство Primary Key, не уточняя, что он не должен быть пустым (Not Null). Ключевые слова Primary Key сами по себе уже говорят, что столбец CustomerID не будет иметь пустых занчений. Для уникальных столбцов, однако, пустые значения возможны.

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

Значения типа Char имеют фиксированную длину. Если столбец Name определен как Char(25), это означает, что каждое значение столбца Name будет храниться в виде строки длиной 25 символов, независимо от того, какова реальная длина имени клиента. При необходимости имена будут дополняться пробелами до 25 символов. Значения типа VarChar могут иметь разную длину. Если название страны состоит всего из четырех символов, то только эти четыре символа и будут храниться в столбце Country.

В табл.~\ref{sql_type} перечислены некоторые из типов данных, поддерживаемых в СУБД Oracle

\begin{table}[!ht]
\caption{Типы данных SQL в СУБД Oracle}\label{sql_type}
\begin{tabular}{p{0.2\textwidth}|p{0.74\textwidth}}
\hline \bf{Тип данных} & \bf{Описание}  \\
\hline BLOB & Большой двоичный объект. Может быть длиной до 4 Гбайт \\
\hline CHAR(n) & Текстовое поле фиксированной длины n. Максимум 2000 символов \\
\hline DATE & Поле длиной 7 байт, содержащее дату и время \\
\hline INT & Целое число длиной 38 знаков \\
\hline NUMBER(n,d) & Число длиной n с d знаками после запятой \\
\hline VARCHAR(n) или VARCHAR2(n) & Текстовое поле переменной длины до n символов. Максимальное значение n=4000 \\
\hline
\end{tabular}
\end{table}

\vspace{0.3cm}
\noindent
{\large \bf{Определение первичных и альтернативных ключей с помощью оператора ALTER}}
\vspace{0.2cm}

\noindent
После того как таблица определена, ее структуру, свойства и ограничения можно изменить, используя оператор ALTER. Так, в листинге~\ref{sql_alter} представлен альтернативный способ определения первичного ключа, при котором сначала определяется таблица, а потом ее определение модифицируется оператором ALTER. Оператор CREATE TABLE определяет все столбцы таблицы CUSTOMER, но ни один из них не указывается в качестве первичного ключа. Затем при помощи оператора ALTER TABLE вводится новое ограничение под названием CustomerPK, которое определяет столбец CustomerID как первичный ключ.

\li\label{sql_alter}
\verbatimtabinput[4]{list_2_2.sql}



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

Оба способа определения первичных ключей для таблиц CUSTOMER (листинг~\ref{sql_create} и листинг~\ref{sql_alter}) являются правильными. Различие состоит в том, что во втором листинге разработчик указал явно имя органичения первичного ключа. Ограничению первичного ключа таблицы CUSTOMER (листинг~\ref{sql_create}) также будет дано имя, но выберет его уже СУБД, что очень часто затрудняет задачи администрирования данных. Поэтому второй метод более предпочтителен.

Определение таблицы ARTIST в листинге~\ref{sql_alter} демонстрирует еще один способ определения первичного ключа. Здесь ограничение определяется в теле оператора CREATE, после того как определены все столбцы. Используя этот подход, разработчик может присваивать имена ограничениям в момент создания таблиц, не прибегая к использованию оператора ALTER. 

\li\label{sql_foreign}
\verbatimtabinput[4]{list_2_3.sql}

Композитный ключ определяется путем перечисления имен атрибутов в скобках. Первичный ключ таблицы CUSTOMER\_ARTIST\_INT представляет собой сочетание \{ArtistID, CustomerID\}. Композитный первичный ключ не может быть определен с помощью того метода, который представлен в листинге~\ref{sql_create}.

Посредством оператора ALTER можно также определять внешние ключи (см. листинг~\ref{sql_foreign}). Ограничение Customer\_Artist\_Int\_ArtistFK указывает, что столбец ArtistID является внешний ключом, который указывает на столбец ARTIST.ArtistID. Аббревиатура FK означает внешний ключ (foreign key). В определении внешнего ключа можно указать процедуру обеспечения ссылочной целостности при удалении: ON DELETE CASCADE.

\vspace{0.3cm}
\noindent
{\large \bf{Операторы DROP}}
\vspace{0.2cm}

\noindent
Одним из самых полезных операторов определения данных SQL является оператор DROP TABLE. Но он одновременно является и одним из самых опасных, поскольку удаляет таблицу из базы данных \emph{вместе со всеми содержащимися в ней данными}. Если необходимо удалить из базы данных таблицу CUSTOMER и все содержащиеся в ней данные, то можно использовать следующий оператор:
\begin{verbatim}
DROP TABLE CUSTOMER
\end{verbatim}

Оператор DROP TABLE не выполняется, если таблица содержит или может содержать значения, необходимые для соблюдения ограничений ссылочной целостности. Например, столбец ArtistID таблицы ARTIST может содержать значения, необходимые для соблюдения ограничения внешнего ключа Customer\_Artist\_Int\_ArtistFK. Попытка передать СУБД на выполнение оператор DROP TABLE ARTIST окончится неудачей и система выдаст сообщение об ошибке.

Если необходимо удалить таблицу ARTIST, нужно сначала удалить либо ограничение внешнего ключа Customer\_Artist\_Int\_ArtistFK, либо всю таблицу CUSTOMER\_ARTIST\_INT. Удалить ограничение можно при помощи следующего оператора:
\begin{verbatim}
ALTER TABLE CUSTOMER_ARTIST_INT 
	DROP CONSTRAINT Customer_Artist_Int_ArtistFK
\end{verbatim}

В другой главе будут рассмотрены дополнительные применения оператора ALTER.

\section{Средства запроса данных языка SQL}
\noindent
Создав таблицу, можно записывать в нее данные, изменять их значения и удалять данные из таблицы. Предполагается, что данные, приведенные в табл.~\ref{ta}-\ref{tc} уже  введены в базу данных. Операторы, которые позволяют добавлять, модифицировать и удалить строки в таблицах будут рассмотрены в разделе~\ref{sec:modif}.

\vspace{0.3cm}
\noindent
{\large \bf{Чтение заданных столбцов из одиночной таблицы}}
\vspace{0.2cm}

\noindent
Следующий оператор запросит (прочитает) три из пяти столбцов таблицы ARTIST:
\begin{verbatim}
SELECT	Name, Nationality, BirthDate
FROM		ARTIST;
\end{verbatim}

Имена запрашиваемых столбцов перечисляются после ключевого слова SELECT, а имя отношения, из которого считываются данные, указываются после ключевого слова FROM. Результатом этого оператора при использовании данных из таблицы ARTIST (см. табл.~\ref{ta}) будет следующая таблица:\\

\noindent
\begin{tabular}{p{0.15\textwidth} p{0.15\textwidth} p{0.2\textwidth}}
\hline 
Miro & Spanish & 1870\\
Kandinsky & Russian & 1854\\
Frings & US & 1700\\
Klee & German & 1900\\
Moos & US & <NULL>\\
Tobey & US & <NULL>\\
Matisse & French & <NULL>\\
Chagall & French & <NULL>\\
\hline
\end{tabular}\\

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

Порядок столбцов в результирующей таблице определяется порядком следования их имен после ключевого слова SELECT. Предположим, что порядок имен столбцов в операторе SELECT будет следующим:
\begin{verbatim}
SELECT	Nationality, Name, BirthDate
FROM		ARTIST;
\end{verbatim}

Результат работы оператора будет следующим:\\

\noindent
\begin{tabular}{p{0.15\textwidth} p{0.15\textwidth} p{0.2\textwidth}}
\hline 
Spanish & Miro & 1870\\
Russian & Kandinsky & 1854\\
US & Frings & 1700\\
German & Klee & 1900\\
US & Moos & <NULL>\\
US & Tobey & <NULL>\\
French & Matisse & <NULL>\\
French & Chagall & <NULL>\\
\hline
\end{tabular}\\

Следующий оператор SELECT извлекает из таблицы ARTIST только столбец Nationality:
\begin{verbatim}
SELECT	Nationality
FROM		ARTIST;
\end{verbatim}

Результатом будет таблица:\\

\noindent
\begin{tabular}{p{0.15\textwidth}}
\hline 
Spanish\\
Russian\\
US\\
German\\
US\\
US\\
French\\
French\\
\hline
\end{tabular}\\

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

Если нужно, чтобы СУБД нашла и удалила повторяющиеся строки, при запросе необходимо использовать ключевое слово DISTINCT:
\begin{verbatim}
SELECT	DISTINCT Nationality
FROM		ARTIST;
\end{verbatim}

Результат будет иметь вид:\\

\noindent
\begin{tabular}{p{0.15\textwidth}}
\hline 
Spanish\\
Russian\\
US\\
German\\
French\\
\hline
\end{tabular}\\

\section{Средства модификации данных языка SQL}\label{sec:modif}
