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

SQL

Глава 1. Реляционные базы данных. Введение

Введение

SQL (произносится обычно "СЭКВЭЛ" (или, более англообразно — СКЬЮЭЛ)) означает Структурированный Язык Запросов.

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

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

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

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

Стандарт SQL определяется ANSI (Американским Национальным Институтом Стандартов) и в данное время также принимается ISO (Международной организацией по стандартизации). Однако большинство коммерческих программ БД расширяют SQL без уведомления ANSI, добавляя разные особенности в этот язык, которые, как они считают, будут весьма полезны.
Иногда это несколько нарушает стандарт языка, хотя хорошие идеи имеют тенденцию развиваться и становиться стандартами рынка в силу полезности своих качеств.

В этой книге мы будем в основном следовать стандарту ANSI, но одновременно иногда будем давать и некоторые наиболее распространённые отклонения от его стандарта.

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

ПРЕЖДЕ ЧЕМ ВЫ СМОЖЕТЕ ИСПОЛЬЗОВАТЬ SQL, вы должны понять, что такое реляционные базы данных.

В этой главе мы объясним и покажем, насколько РБД полезны. Мы не будем обсуждать SQL именно здесь, и, если вы уже знаете эти понятия достаточно хорошо, вы можете просто пропустить эту главу. В любом случае вы должны просмотреть три таблицы, которые предоставляются и объясняются в конце главы; они станут основой наших примеров в этой книге. Вторая копия этих таблиц находится в Приложении E, и мы рекомендуем скопировать их для удобства ссылки к ним.

Понятие реляционной базы данных

База данных — это структурированный набор постоянно хранимых данных. Постоянность означает, что данные не уничтожаются по завершении программы или пользовательского сеанса, в котором они были созданы. В реляционной базе данных информация хранится в виде двухмерных таблиц. Возможно использование и других структур — когда-то базы данных имели иерархическую или сетевую организацию. Однако реляционный подход доказал свои преимущества для большинства применений и в настоящее время является промышленным стандартом. Реляционная модель была предложена в 1970-е гг. Тедом Коддом, работавшим тогда в IBM.

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

Таблица 1.1
NameAddressCountry
Gerry Farish127 Primrose Ave., SFUSA
Celia Brock246 3rd St., SonomaUSA
Julio Abregon778 Avenida Tarragon, PatzcauroMEX

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

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

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

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

Таблица 1.2
Id_NumNameAddressCountry
1007Gerry Farish127 Primrose Ave., SFUSA
1008Celia Brock246 3rd St., SonomaUSA
1010Julio Abregon778 Avenida Tarragon, PatzcauroMEX

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

Необходимость второй таблицы

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

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

Для этого можно поместить в таблицу Client_Phone первичный ключ из таблицы Clients. Эти номера уникальны, поэтому мы всегда будем знать, какому клиенту ссответствует данный номер. Столбуц id_num в таблице Client_Phone называется внешним ключом (foreign key). Говорят, что он ссылается на первичный ключ таблицы Clients. Данное отношение показано в таблице 1.3. Если все значения внешнего ключа таблицы Client_Phone ссылаются на значения, которые действительно присутствуют в таблице Clients, то система обладает ссылочной целостностью (referential integrity). В противном случае имеется повод для беспокойства, т.к. база данных содержит телефонные номера клиентов, которые не существуют или не могут быть идентифицированы.

Таблица 1.3
Id_NumPhoneType
10074156479772home
10087074568232work
10087079402092home

Для таблицы Client_Phone также необходим первичный ключ — его должна иметь каждая таблица. Мы не можем использовать id_num, поскольку он не является уникальным (повторяется для телефонных номеров одного клиента). А что если применить сами телефонные номера? Это лучше, но возможна ситуация, когда в одном доме или офисе есть два клиента — их телефонные номера нужно будет хранить отдельно. При использовании номера телефона в качестве первичного ключа мы смогли бы задействовать его только в одной строке таблицы Client_Phone, а, следовательно, ассоциировать только с одним id_num.

Первичный или внешний ключ необязательно должен состоять из одного столбца. Можно скомбинировать столбцы id_num и phone. Такая комбинация будет уникальной, поскольку при повторном указании того же номера для какого-либо клиента мы получим две одинаковые записи, одну из которых в любом случае придется удалить. Итак, комбинация id_num и phone является логическим первичным ключом для таблицы Client_Phone. Ключ, состоящий более чем из одного столбца, называется составным (composite) или многоколоночным (multicolumn).

Соединение таблиц

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

Операция извлечения информации из базы данных называется запросом (query). В SQL запросы реализуются с помощью оператора SELECT. Запрос, который одновременно извлекает данные из более чем одной таблицы путем сопоставления столбцов одной таблицы столбцам других таблиц, называется соединением (join). Соединение собирает вместе все то, что мы расположили в разных таблицах в соответствии с реляционной моделью. С помощью соединения можно получить полную информацию о каждом клиенте: имя, адрес, телефон и т.д.

Имя, номер и тип столбца

В отличие от строк, столбцы таблицы (называемые также полями) упорядочиваются и именуются. Так, в таблице Clients (см. таблицу 1.2) третий столбец слева содержит адрес. Во избежание неоднозначности все столбцы таблицы должны иметь разные имена. Имена следует выбирать так, чтобы они отражали содержимое столбца. В наших примерах мы будем использовать в качестве имен столбцов аббревиатуры, такие, как cname для имени покупателя (customer name) и odate для даты заказа (order date). Кроме того, мы включили в каждую таблицу один числовой столбец, служащий первичным ключом (см. ниже).

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

Работа с реляционной базой данных

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

Первый из них относится к группированию таблиц. Должны ли все таблицы в базе данных быть связаны между собой? Нет. Группа взаимосвязанных таблиц называется схемой (schema). База данных может содержать любое количество схем. Первоначально (в SQL89) все таблицы, подконтрольные одному пользователю, автоматически входили в одну схему. Стандарт SQL92 изменил эту ситуацию, но вы по прежнему можете встретиться со старой практикой.

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

  • Они идентифицируются с помощью процедуры входа, обычно включающей в себя запрос имени пользователя и пароля.
  • После входа они запускают сеанс (session) работы с СУБД, называемый также соединением (connection). Сеанс продолжается до завершения работы с базой данных. В течение сеанса выдается последовательность инструкций (команд). Инструкции из одновременных сеансов одного или нескольких пользователей образуют независимые последовательности.
  • Они имеют набор привилегий, определяющих разрешенные и запрещенные действия.
  • Так же, как пользователи ОС владеют некоторым набором файлов и каталогов и могут получать доступ к различным ресурсам, пользователи БД обычно владеют одной схемой и при этом могут обращаться к другим. В зависимости от конкретной СУБД пользователю базы данных может принадлежать одна или несколько схем. Приложение, которому необходим доступ к схеме, часто действует под видом этого пользователя базы данных независимо от того, каким пользователем ОС оно было запущено. Это существенно упрощает работу.

Простая схема базы данных

Таблицы 1.4, 1.5 и 1.6 образуют простую реляционную базу данных. Она мала, так что с ней легко работать, но в то же время содержит все необходимые компоненты для иллюстрации основных принципов и приемов применения SQL. Эти таблицы вы найдете также в Приложении E.

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

Таблица 1.4 Salespeople (Продавцы)

      ----------------------------------------------
        SNUM  |   SNAME   |  CITY        |   COMM
      --------|-----------|--------------|----------
        1001  |  Peel     |  London      |    .12
        1002  |  Serres   |  San Jose    |    .13
        1004  |  Motika   |  London      |    .11
        1007  |  Rifkin   |  Barcelona   |    .15
        1003  |  Axelrod  |  New York    |    .10
      ----------------------------------------------


Таблица 1.5 Customers (Покупатели)

       ----------------------------------------------
        CNUM  |  CNAME     | CITY    | RATING | SNUM
       -------|------------|---------|--------|------
        2001  |  Hoffman   | London  |   100  | 1001
        2002  |  Giovanni  | Rome    |   200  | 1003
        2003  |  Liu       | SanJose |   200  | 1002
        2004  |  Grass     | Berlin  |   300  | 1002
        2006  |  Clemens   | London  |   100  | 1001
        2008  |  Cisneros  | SanJose |   300  | 1007
        2007  |  Pereira   | Rome    |   100  | 1004
       ----------------------------------------------

Таблица 1.6 Orders (Заказы)

       -----------------------------------------------
        ONUM  |    AMT    |    ODATE    | CNUM | SNUM
       -------|-----------|-------------|------|------
        3001  |    18.69  |  10/03/1990 | 2008 | 1007
        3003  |   767.19  |  10/03/1990 | 2001 | 1001
        3002  |  1900.10  |  10/03/1990 | 2007 | 1004
        3005  |  5160.45  |  10/03/1990 | 2003 | 1002
        3006  |  1098.16  |  10/03/1990 | 2008 | 1007
        3009  |  1713.23  |  10/04/1990 | 2002 | 1003
        3007  |    75.75  |  10/04/1990 | 2004 | 1002
        3008  |  4723.00  |  10/05/1990 | 2006 | 1001
        3010  |  1309.95  |  10/06/1990 | 2004 | 1002
        3011  |  9891.88  |  10/06/1990 | 2006 | 1001
       -----------------------------------------------

Поле snum таблицы Customers показывает, к какому продавцу прикреплен покупатель. Номер snum относится к таблице Salepeople, которая содержит информацию о продавцах. Очевидно, что продавцы, к которым прикреплены покупатели, должны существовать; иными словами, значения snum из таблицы Customers должны также присутствовать в таблице Salespeople. Если данное условие выполняется, то система находится в состоянии ссылочной целостности.

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

Столбцы таблицы Salespeople

    СТОЛБЕЦ     СОДЕРЖАНИЕ
    ---------   ---------------------------------------------------
    snum        уникальный номер назначенный каждому продавцу
                ("номер служащего").
    sname       имя продавца.
    city        местонахождение продавца (город).
    comm        комиссионные продавцов в десятичной форме.

Столбцы таблицы Customers

    СТОЛБЕЦ     СОДЕРЖАНИЕ
    ---------   ---------------------------------------------------
    cnum        уникальный номер, назначенный каждому покупателю.
    cname       имя заказчика.
    city        местонахождение покупателя (город).
    rating      код, указывающий уровень предпочтения данного покупателя перед 
                другими. Более высокий номер указывают на большее предпочтение (рейтинг).
    snum        номер продавца, назначенного этому покупателю (из таблицы Продавцов).

Столбцы таблицы Orders

    СТОЛБЕЦ     СОДЕРЖАНИЕ
    ---------   ---------------------------------------------------
    onum        уникальный номер, данный каждой покупке.
    amt         сумма покупки.
    odate       дата покупки.
    cnum        номер покупателя, делающего покупку (из таблицы Покупателей).
    snum        номер продавца, совершившего продажу (из таблицы Продавцов).

Работа с SQL

  1. Какое поле таблицы Заказчиков является первичным ключом?
  2. Что является столбцом 4 из таблицы Заказчиков?
  3. Как по другому называется строка? Столбец?
  4. Почему вы не можете запрашивать для просмотра первые пять строк таблицы?

(См. ответы в Приложении A.)