Вы - -й посетитель этой странички 

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

Таблица "Учителя — предметы"

Номер учителя

 

Номер предмета

 

1

 

1

 

1

 

2

 

2

 

4

 

3

 

1

 

3

 

4

 

4

 

2

 

4

 

4

 

Согласно таблице "Учителя — предметы" Иванов Иван Иванович ведет информатику и физику, Петров Петр Петрович — математику, Сидоров Сидор Сидорович — информатику и физику, Сократов Сократ Сократович — физику и математику. Таким образом, содержательная связь "многие ко многим" может быть реализована посред­ством введения дополнительной таблицы и двух связей "один ко многим".

Реляционные операторы выбора, проектирования и объединения

В [4] приводится следующее неформальное определение реляционной СУБД, принадлежащее С.Дейту. Соглас­но ему реляционная СУБД должна удовлетворять двум основным требованиям:

• вся информация в ней должна быть представлена в виде таблиц;

• она должна поддерживать три реляционных оператора: выбора, проектирования и объединения. Кратко поясним, о каких именно операторах идет речь (здесь мы рассмотрим эти операторы в общем виде, их реализацию на языке SQL мы увидим позже).

Оператор выбора

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

ВЫБОР ВСЕХ ПОЛЕЙ ИЗ ТАБЛИЦЫ "Оценки" ГДЕ ПОЛЕ "Оценка">3.

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

Номер ученика

 

Номер урока

 

Оценка

 

1

 

1

 

5

 

2

 

2

 

4

 

1

 

2

 

4

 

Оператор проектирования

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

Например, если нам нужно получить лишь список учеников, то из таблицы "Ученики" требуется выбрать лишь один столбец "Имя, фамилия":

ВЫБОР   ПОЛЯ   "Имя,    фамилия"   ИЗ   ТАБЛИЦЫ   "Ученики".


Результатом операции проектирования является таблица. Для приведенного примера она имеет следующий вид:

Имя, фамилия

Петр Первый
Александр Второй
Александр Македонский

Отметим, что мы не случайно использовали одно и то же слово ВЫБОР для обозначения и оператора выбора, и оператора проектирования (и будем использовать его далее для обозначения оператора объединения). В языке SQL все три оператора также реализуются посредством одной команды SELECT.

Оператор объединения

На практике оператор объединения используется для выбора данных из нескольких связанных таблиц. Однако при решении содержательных задач для этого требуется не только оператор объединения, но и операторы выбора и проектирования (речь идет о композиции операторов, которую мы обсудим ниже). В чистом виде объедине­ние довольно "утомительная операция. Рассмотрим, что получается в результате простого объединения таблиц "Учителя" и "Предметы". Для этого запишем оператор объединения:

ВЫБОР ВСЕХ ПОЛЕЙ ИЗ ТАБЛИЦ "Учителя", "Предметы".

А вот результат этого оператора (как и в случае операторов выбора и проектирования, результатом объединения является таблица):

Номер учителя

 

Фамилия, имя, отчество

 

Номер предмета

 

Название предмета

 

1

 

Иванов Иван Иванович

 

1

 

Информатика

 

1

 

Иванов Иван Иванович

 

2

 

Физика

 

1

 

Иванов Иван Иванович

 

3

 

Биология

 

1

 

Иванов Иван Иванович

 

4

 

Математика

 

2

 

Петров Петр Петрович

 

1

 

Информатика

 

2

 

Петров Петр Петрович

 

2

 

Физика

 

2

 

Петров Петр Петрович

 

3

 

Биология

 

2

 

Петров Петр Петрович

 

4

 

Математика

 

3

 

Сидоров Сидор Сидорович

 

1

 

Информатика

 

3

 

Сидоров Сидор Сидорович

 

2

 

Физика

 

3

 

Сидоров Сидор Сидорович

 

3

 

Биология

 

3

 

Сидоров Сидор Сидорович

 

4

 

Математика

 

4

 

Сократов Сократ Сократович

 

1

 

Информатика

 

4

 

Сократов Сократ Сократович

 

2

 

Физика

 

4

 

Сократов Сократ Сократович

 

3

 

Биология

 

4

 

Сократов Сократ Сократович

 

4

 

Математика

 

Как видите, от такого объединения толку мало. Но толку мало и от операторов выбора и проектирования в чистом виде. Вся мощь реляционных операторов проявляется в их композиции. Поскольку результатами всех операторов являются таблицы, к этим таблицам-результатам можно вновь применять реляционные операторы. Рассмотрим соответствующий пример. Но сначала договоримся записывать поле X в таблице А в виде А.Х. То есть поле "Номер учителя" в таблице "Учителя" мы будем обозначать как "Учителя"."Номер учителя", а поле с таким же названием в таблице "Учителя — предметы" как "Учителя — предметы"."Номер учителя". На основе таблиц "Учителя", "Предметы" и "Учителя — предметы" получим список всех учителей информатики:

 

ВЫБОР   ПОЛЯ   "Учителя"."Фамилия,    имя,    отчество"

ИЗ   ТАБЛИЦ   "Учителя",    "Предметы",    "Учителя    предметы"

ГДЕ      "Предметы"."Название   предмета"="Информатика"   И

"Предметы"."Номер   предмета"="Учителя  — предметы"."Номер  предмета"   И
 
"Учителя  — предметы"."Номер   учителя"="Учителя"."Номер   учителя"

 

Здесь посредством оператора объединения объединяются три таблицы: "Учителя", "Предметы" и "Учителя — предметы". Получается о-о-чень большая таблица. Затем с помощью оператора выбора из нее отбираются строки, удовлетворяющие условию, сформулированному в части ГДЕ. Получается таблица поменьше. И, наконец, поскольку нас интересуют лишь фамилии, имена и отчества, из последней таблицы берется лишь один столбец. Для этого используется оператор проектирования.

 


Что такое запрос?

Запросом называется любая операция в СУБД. Бывают запросы на создание и удаление баз данных, на создание и удаление таблиц, на модификацию таблиц и модификацию структуры таблиц, на выбор информации и т.д.

Что является результатом запроса?

Мы бы не стали акцентировать внимание на этом вопросе, если бы не известный тезис, который очень часто встречается в литературе. Звучит он примерно так: согласно реляционной модели результатом любого запроса является таблица. Самое интересное то, что тезис этот, конечно, правильный. И MySQL по мере сил старается представлять результаты запросов в виде таблиц. Но, к сожалению, не все так просто. С рассмотренными выше реляционными операторами выбора, проектирования и объединения все понятно: они действительно перерабаты­вают таблицы в таблицы. А, допустим, нам захочется получить не список, а только количество хорошистов? Что такое количество? Число, конечно. MySQL попробует сделать "хорошую мину" и покажет нам табличку, состоя­щую из одной ячейки, в которой будет записано искомое количество. Но сути это, конечно, не изменит. Так что вопрос о результате запроса в общем случае не имеет простого ответа.

§ 5. Основы языка SQL

Поскольку язык SQL создавался для пользователей-непрофессионалов, он является очень простым. Фактически SQL представляет собой набор (правда, довольно большой) команд с достаточно простым и интуитивно понятным синтаксисом. Следует отметить, что, поскольку на практике едва ли приходится иметь дело с двумя-тремя десят­ками команд (а постоянно используется и того меньше), специально "изучать" SQL не требуется — наиболее употребительные команды сразу запоминаются сами собой. Но, разумеется, все равно полезно иметь под рукой справочник. В этом параграфе рассматривается ряд наиболее употребительных команд SQL. Во всех случаях син­таксис команд будет "сужен", то есть мы опустим некоторые не существенные для нашего изложения дополни­тельные параметры ряда команд.

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

Команда USE

Посредством команды use выбирается активная база данных. Именно к этой базе данных будут адресоваться все запросы, в которых имя базы данных не указано явно.

Синтаксис команды USE

USE <имя базы данных>

Пример использования команды USE

USE test;

Поскольку база данных test создается при установке MySQL, вы можете сразу опробовать команду USE в работе. База данных, которая становится активной при запуске клиента mysql, может быть задана в командной строке или в файле конфигурации. Если не сделано ни то, ни другое (как в нашем случае) , то активная база данных не определена. Получить имя активной базы данных можно посредством команды select database ( ) . Ниже показан соответствующий диалог — сначала активная база данных не определена, затем использована команда USE и вновь запрошено имя активной базы данных.

Пример 3

mysql>  SELECT  DATABASE ();

-----------------------------
|  DATABASE ( )    |
----------------------------
|                            |
-----------------------------
1 row in set (0.00 sec)
mysql>  USE  test;
Database  changed
mysql>  SELECT  DATABASE ();

--------------------------
|  DATABASE ( )    |
---------------------------
|    test                     |
--------------------------
1 row in set (0.00 sec)

Команда SHOW

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

Синтаксис и примеры использования команды SHOW
Пример 4

Пример использования команды SHOW DATABASES был приведен выше. Покажем результат применения команды SHOW TABLES (напомним, мы предполагаем, что команды, описываемые в этом параграфе, рассматрива­ются последовательно, таким образом, база данных test должна быть активной).

mysql>  SHOW  TABLES;
Empty  set   (0.06 sec)

Поскольку база данных test пуста, результатом команды SHOW TABLES является пустое множество.

Команда CREATE DATABASE

Посредством команды CREATE DATABASE можно создавать новые базы данных.

Синтаксис команды CREATE DATABASE

create database <имя базы данных>

Пример использования команды CREATE DATABASE

CREATE  DATABASE  testl;

Пример 5

Обратите внимание на то, что при создании база данных не становится активной.

mysql> CREATE DATABASE testl;
 Query OK,   1   row affected   (0.00   sec)

mysql> SHOW DATABASES;
------------------
|  DATABASE ( )  |
------------------
|    mysql       | 

|    test        |

|    testl       |

------------------
3   rows in set   (0.00   sec) mysql>  SELECT DATABASE ()

------------------
|  DATABASE ( )    |
--------------------
|    test          |
--------------------
1 row in set (0.00 sec)

Команда CREATE TABLE

Команда CREATE TABLE предназначена для создания таблиц в базе данных.

Синтаксис команды CREATE TABLE

create table < имя таблицы> ( <описание таблицы>)

 

содержащиеся в файле, следует ввести команду \ .

Теперь, когда мы избавлены от необходимости вводить все команды вручную, вернемся к рассмотрению команды CREATE TABLE. Создадим в базе данных test таблицу с именем tablel, содержащую три ноля — текстовое (строковое) поле field1, целочисленное ноле field2 и поле field3, содержащее данные типа "дата". Для этого воспользу­емся следующим оператором CREATE TABLE, который запишем в файл createtable.sql в каталог С: \mysql\queries:

CREATE  TABLE  tablel
 (

field1 VARCHAR(20)   NOT NULL  DEFAULT  "none",
field2 INT,
field3 DATE );

Для описания строкового поля field1 мы использовали тип VARCHAR(20) . В терминах Турбо Паскаля, тип VARCHAR соответствует тину STRING, a VARCHAR (20 ) соответственно тину STRING [20 ]. Кроме того, мы объявили данное ноле непустым (NOT NULL). Если при добавлении новой строки в таблицу значение этого ноля не будет задано, то ему будет присвоено значение "по умолчанию" — "nоnе". Для описания целочисленного поля field2 использован тип INT, а для описания поля типа "дата", значения которого имеют вид "YYYY-MM-DD", — тип DATE. (Такой формат представления дат стандартизирован в языке SQL.) Разумеется, в SQL имеются и другие типы данных. Перечень типов, поддерживаемых MySQL, диапазоны их значений и прочая информация, связанная с типами данных, содержится в документации, которая при установке MySQL размещается в каталоге Docs. В частности, информация о типах данных находится но адресу С : /mysql/Docs/manual.html#Storage_requirements (раздел "7.3.1 Column Type Storage Requirements").

Команда INSERT

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

Синтаксис команды INSERT

INSERT INTO <имя таблицы> SET <пары вида имя_столбца=значение, разделенные запятыми>

Пример использования команды INSERT

INSERT INTO tablel SET field1="Informatica",  field2=400,  field3="2002-06-30"; заполнения учебной базы, рассмотренной в §6, используется следующая модификация команды INSERT:

INSERT  INTO <имя таблицы> VALUES

Приведем соответствующий пример:

 

INSERT  INTO table1 VALUES( "Informatica",400,"2002-06-30");

 

Команда SELECT

Команду SELECT часто называют основной командой языка SOL. И но праву. С помощью этой команды организуются все наиболее употребительные запросы. Кроме того, посредством команды SELECT выполняются три основных реляционных оператора: выбора, проектирования и объединения. Поэтому команде SELECT мы уделим на порядок больше внимания, чем остальным командам SQL. Отметим, что команда SELECT может и не обра­щаться к данным, содержащимся в базе. В примере 2 была показана команда SELECT, которая возвращала неко­торую служебную информацию. Формально говоря, основными аргументами команды SELECT являются имена полей, а результатом — таблица, содержащая всевозможные наборы значений этих полей.

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

Вернулись? Продолжаем. Сначала приведем общий вид команды SELECT (еще раз напомним, что мы несколько сужаем синтаксис рассматриваемых команд).

 

Синтаксис команды SELECT

select <запрашиваемая информация>

[from < источник информации>]

[ where <условие> ]

[GROUP by < список полей через запятую>

[having <усло6ие>] ]

[ORDER BY   <выражение>   [ASC[DESC]]

[limit  [<с какой строки выдать>,] < сколько строк выдавать>]

 

Как обычно, в квадратные скобки заключены необязательные части. Рассмотрим все части команды SELECT по отдельности.

Часть < запрашиваемая информация>

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

Обратите внимание на то, как задается заголовок столбца. Сравните:

Перейдем к более содержательным примерам запрашиваемой информации. Рассмотрим следующий запрос:

Поскольку в таблице student довольно много записей, мы немного забежали вперед и воспользовались ограничителем LIMIT, посредством которого можно задавать количество строк результата запроса, которые должны быть выведены. В примере 10 на месте запрашиваемой информации указан символ "*". Этот символ означает "все поля". Если нам требуется вывести лишь некоторые поля (выполнить операцию проектирования) , то их надо перечислить явно:

 

В следующем примере запрашивается информация о количестве записей в таблице student:

 

В § 4 мы кратко затронули вопрос о том, что является результатом запроса. И отметили, что в соответствии с концепцией реляционных баз данных MySQL старается представлять результаты всех запросов в виде таблиц. Это, в частности, продемонстрировано в примере 12.

COUNT является одной из так называемых "агрегирующих функций", которые являются мощным инструментом конструирования запросов. Мы еще вернемся к ним при рассмотрении части GROUP BY.

Часть FROM

В части FROM перечисляются таблицы, которые требуются для выполнения запроса. Обратите внимание на то, что здесь требуется указывать все таблицы, а не только те, поля которых упоминаются в части < запрашиваемая информация> . Имена таблиц при этом разделяются запятыми. Фактически мы уже приводили соответствующий пример в § 4 при рассмотрении операции объединения. Но там использовалась символическая форма записи оператора SELECT. Ниже мы увидим, как записать упомянутый пример на языке SQL.

Часть WHERE

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

Пример 13

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

Пример 14

Если нам требуется получить список всех девушек, которые когда-либо получали оценку, превышающую 90 Баллов, то необходимо использовать сложное условие и выбирать данные из двух таблиц: student и score.

На первый взгляд все нормально. Но это только на первый. Почему в полученном списке Abby упоминается дважды? Вспомним (см. § 4), что мы имеем дело с композицией реляционных операторов. Сначала выполняется оператор объединения, затем — выбора и, наконец, последним выполняется оператор проектирования. Чтобы это стало более очевидно, уберем оператор проектирования, оставив только два первых.

 

В результате объединения таблиц student и score получается огромная таблица, содержащая 5363 строки. Как мы это вычислили? Вот так:

Затем из этой огромной таблицы выбираются все строки согласно условию, записанному в WHERE . И мы бы, может быть, ничего и не заметили, если бы Abby не получила оценку, превышающую 90, сразу за два контрольных меро­приятия, которые имеют идентификаторы event_id 3 и 6. Кстати, поинтересуемся, что это были за мероприятия:

 

Мы видим, что оба контрольных мероприятия были тестами и проводились соответственно 9.9.1999 и 1.10.1999. Так как же быть? Для того чтобы исключить из результата запроса повторяющиеся строки в разделе запрашиваемая информация, следует использовать ключевое слово DISTINCT. (В некоторых диалектах SQL следует использо­вать слово DISTINCTROW, MySQL понимает оба варианта.) Приведем соответствующий пример:

 

Если мы не используем DISTINCT, то "по умолчанию" считается, что используется режим ALL. Слово ALL можно задавать и явно, хотя большого смысла в этом нет.

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

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

 

В условиях можно использовать операции, функции и специальные операторы, описание которых содержится в электронной документации к MySQL ("бумажная" версия документации содержит более тысячи страниц убористого текста, поэтому мы не имеем возможности сколько-нибудь подробно описать здесь даже наиболее часто используемые операции и функции). Но один специальный оператор мы упомянем, это оператор LIKE. Предположим, что нам требуется получить список студентов, имена которых начинаются с буквы "L". Это можно сделать посредством следующего запроса:

 

Как видите, таких всего два. Теперь получим список студентов, имена которых состоят ровно из 5 символов:

 

Третья часть