
Технология проектирования и администрирования баз данных и систем данных-Конспект3
.pdf
- 21 -
CLERK
SALESMAN
SALESMAN
MANAGER
SALESMAN
MANAGER
MANAGER
ANALYST
PRESIDENT
SALESMAN
CLERK
CLERK
ANALYST
CLERK
Поскольку в вышеприведенном запросе нет клаузы WHERE, будут возвращены все значения в колонке JOB таблице EMP. Как видно, имеются дублирующие строки в колонке (это значит, что много работников имеют одну должность). Эти дублирующие значения можно исключить, задавая в клаузе SELECT слово DISTINCT. Ключевое слово DISTINCT используется в следующем запросе:
SELECT DISTINCT JOB --- ключевое слово DISTINCT FROM EMP;
JOB
CLERC
SALESMAN
MANAGER
ANALYST
PRESIDENT
Хотя в исходной таблице имеется 14 (частично повторяющихся) должностей, в распечатке их только 5 уникальных.
Контрольные вопросы
1.В каких случаях целесообразно применять режим предохранения от выбора строк-дубликатов ?
2.Какая SQL-клауза задает режим запрета вывода строк-дубликатов ?
2.8.Запросы к нескольким таблицам
Запрос типа JOIN

- 22 -
До сих пор все примеры относились к работе с одной таблицей (ЕМР или DEPT). Запрос типа JOIN (соединение) позволяет выбирать данные из двух или более таблиц и объединять выбранные данные в одной общей таблице.
Предположим, что необходимо узнать, где работает работник по фамилии ALLEN. Просматривая две таблицы в БД, можно видеть, что таблица ЕМР не содержит колонку LOC (местоположение), а эта колонка находится в таблице DEPT. Однако обе таблицы имеют колонку DEPTNO - номер отдела. Именно эти номера, содержащиеся в обеих таблицах, позволят соотнести строки из таблицы ЕМР со строками таблицы DEPT.
Запрашивая таблицу ЕМР, можно найти номер отдела, где работает
ALLEN:
SELECT ENAME,DEPTNO
FROM ЕМР
WHERE ENAME = 'ALLEN';
|
ENAME |
|
DEPTNO |
|
|
||
|
ALLEN |
30 |
И, далее, запрашивая таблицу DEPT, можно найти расположение отдела
30:
SELECT LOC
FROM DEPT
WHERE DEPTNO = 30;
LOC
CHICAGO
В результате использования этих двух запросов выяснилось, что ALLEN работает в Чикаго.
Можно получить тот же самый результат, используя только один запрос типа JOIN. В этом запросе перечисляются названия таблиц, которые запрашиваются в клаузе FROM и имена колонок, сравниваемых в обеих таблицах (то есть общие колонки) в клаузе WHERE:
SELECT ENAME,LOC
FROM ЕМР,DEPT --- запрос к двум таблицам
WHERE ENAME = 'ALLEN'
AND EMP.DEPTNO = DEPT.DEPTNO; --- условие соединения
ENAME LOC

- 23 -
ALLEN CHICAGO
Выражения EMP.DEPTNO и DEPT.DEPTNO позволяют обратиться к заданному столбцу (имя правее точки) нужной таблицы (левее точки).
Условия соединения в клаузе WHERE определяет взаимосвязь между таблицами ЕМР и DEPT. В вышеприведенном примере, например, если DEPTNO в строке таблицы ЕМР совпадает с DEPTNO в строке таблицы DEPT (EMP.DEPTNO=DEPT.DEPTNO); в этом случае говорят, что вышеуказанные таблицы связаны по столбцу DEPTNO (на нижерасположенном рисунке показано стрелкой, подобные обозначения часто используют при логическом проектировании БД):
Таблица EMP
|
EMPNO |
|
|
ENAME |
|
|
JOB |
|
|
DEPTNO |
|
||
|
|
|
|
|
|
|
|
||||||
7499 |
|
|
ALLEN |
|
SALESMAN |
30 |
|
||||||
|
Таблица DEPT |
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|||
|
DEPTNO |
|
|
DNAME |
|
|
LOC |
|
|
|
|
|
|
30 |
|
|
SALES |
|
CHICAGO |
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Соединение данных
Вдобавок к условиям соединения, клауза WHERE содержит условие поиска ENAME='ALLEN', которое требует выбора только строки с работником по имени ALLEN. Таким образом соединяется только эта строка из таблицы ЕМР (в которой содержится значение 30 в поле DEPTNO), со строкой из таблицы DEPT, в которой тоже содержится тот же номер 30.
Можно соединять отдельные строки (как в последнем примере), части таблиц или таблицы целиком. Например, для перечисления названий отделов (информация, содержащаяся только в таблице DEPT) вместе с другими данными о работниках соединим строки из таблицы ЕМР с таблицей DEPT и дополнительно упорядочим результат:
SELECT DNAME,ENAME,JOB,SAL |
(*) |
|||
FROM EMP,DEPT |
|
|
|
|
WHERE EMP.DEPTNO = DEPT.DEPTNO |
||||
ORDER BY DNAME, SAL DESC; |
|
|
||
|
|
|
|
|
DNAME |
ENAME |
JOB |
SAL |
|
ACCOUNTIG |
KING |
PRESIDENT |
5,000.00 |
|
ACCOUNTIG |
CLARK |
MANAGER |
2,460.00 |
|

|
|
- 24 - |
|
|
|
|
|
ACCOUNTIG |
MILLER |
CLERC |
1,300.00 |
RESEARCH |
SCOTT |
ANALYST |
3,000.00 |
RESEARCH |
FORD |
ANALYST |
3,000.00 |
RESEARCH |
JONES |
MANAGER |
2,976.00 |
RESEARCH |
ADAMS |
CLERC |
1,100.00 |
RESEARCH |
SMITH |
CLERC |
800.00 |
SALES |
BLAKE |
MANAGER |
2,850.00 |
SALES |
ALLEN |
SALESMAN |
1,600.00 |
SALES |
TURNER |
SALESMAN |
1,500.00 |
SALES |
WARD |
SALESMAN |
1,250.00 |
SALES |
MARTIN |
CLERC |
950.00 |
Даже этот простой пример дает понятие о мощности языка SQL. При программировании с помощью процедурных языков процедура соединения всего двух таблиц требует составления и отладки достаточно сложной программы (содержащей минимум один вложенный в другой цикл по записям таблиц), которую к тому же непросто сделать эффективной в работе.
Требуемая программа становится значительно более |
сложной и громоздкой |
при увеличении количества соединяемых таблиц, |
время выполнения ее |
возрастает экспоненциально. В очередной раз подчеркнем, что при использовании SQL пользователь сообщает, ЧТО он хочет получить, а не КАК это сделать.
Иерархические и сетевые системы управления базами данных хранят некоторую информацию типа значений и другого типа - указателей. В сетевых системах, например, информация о том, что работник SMITH занимает должность CLERK, хранится как значение в некоем поле. Информация, что SMITH работает в отделе 20, будет храниться как указатель из записи SMITH на запись отдела 20. Только информация, хранимая в виде указателей, может быть использована для сопоставления одной записи другой в сетевой или иерархической базе данных. Решение, хранить ли информацию в виде указателей или значений, должно быть сделано при определении базы данных.
Таким образом, сетевая или |
иерархическая система имеет соотношения, |
основанные на указателях, |
и предопределена как статическая; изменение |
связей потребует перестройки всего файла.
В противоположность этому реляционные БД хранят все данные однотипным способом - как значения, хранимые в полях. Можно использовать любое значение для ассоциирования или соединения одной таблицы с другой и легко определить соотношения между значениями, когда вводится запрос, а не когда создаются сами таблицы.
Таким образом, соотношения в реляционной базе данных являются
основанными |
на значениях и динамическими, |
что обеспечивает |
максимальную |
гибкость, представляемую пользователю в ответ на самые |
|
неожиданные запросы. |
|

- 25 -
Контрольные вопросы
1.Каков формат SELECT-предписания для выполнения запроса данных из нескольких таблиц одновременно ?
2.Каким образом запрос типа JOINT позволяет выбирать данные из нескольких таблиц и объединять их при выводе ?
3.Каким образом при логическом проектировании БД показывают связь таблиц по заданному столбцу (столбцам) ?
4.Постарайтесь составить (на языке уровня Pascal или C) программу, функционально аналогичную вышеприведенному SQL-запросу (*). Насколько проще сформулировать эту задачу с использование SQL ?
1.9.Арифметические операции и функции строк символов |
|
|
В то время как SQL фирмы IBM поддерживал всего 4 |
базовых |
|
арифметических операций (+, -, *, /), современный SQL поддерживает |
||
полный |
набор арифметических функций и функций манипулирования |
|
строками. |
|
|
Арифметические выражения
Для создания арифметического выражения достаточно соединить имена колонок и численные константы арифметическими операторами.
Задача перечисления имен, окладов, комиссионных и сумму окладов плюс комиссионные для каждого продавца решается естественным образом:
SELECT ENAME,SAL,COMM,SAL+COMM --- вычисление суммы FROM EMP
WHERE JOB = 'SALESMAN';
|
ENAME |
|
SAL |
|
COMM |
|
SAL+COMM |
|
|
|
|
||||
ALLEN |
1,600.0 |
300.00 |
1,900.00 |
||||
WARD |
1,250.0 |
500.00 |
1,750.00 |
||||
MARTIN |
1,260.00 |
1,400.00 |
2,660.00 |
||||
TURNER |
1,500.0 |
0.00 |
1,500.00 |
Отметим, что арифметическое выражение (SAL+COMM) выводится как новая колонка в результирующей таблице. Хотя такая колонка, как SAL+COMM, не присутствует в базе данных, она материализовалась как результат запроса, при этом можно работать с ней как с реальной колонкой.

- 26 -
Примеры дополнительных арифметических операторов перечислены ниже.
Функции символьных строк
Арифметические функции позволяют манипулировать численными данными; точно также функции символьных строк, подобные нижеописанным, упрощают манипулирование символьными данными. Например, можно использовать функцию SOUNDEX для поиска одинаково звучащих имен, пишущихся по-разному. Например, найдем всех работников, имена которых созвучно SCHMIDT:
SELECT ENAME FROM EMP
WHERE SOUNDEX(ENAME) = SOUNDEX('SCHMIDT');
ENAME
SMITH
Поддерживаются следующие арифметические операции, функции и
функции символьных строк: |
|
|
|
Арифметические операторы |
Строковые функции |
||
+ |
сложение |
| |
конкатенация |
- |
вычитание |
DECODE |
транслировать |
* |
умножение |
LENGTH |
длина строки |
/ |
деление |
SUBSTR |
подстрока |
POWER |
степень |
ROUND |
округление |
TRUNC |
усечение |
ABS |
модуль числа |
UPPER |
заглавные |
LOWER |
строчные |
SOUNDEX сопоставление |
CAST |
явное |
|
|
по звучанию |
|
преобразование |
|
|
|
типа данных |
Это только часть полного списка арифметических и строковых функций. Смотрите следующие разделы данного учебного пособия для обсуждения групповых функций AVG, SUM,COUNT, MIN, MAX и работы [1...3].
Контрольные вопросы
1.Каким образом осуществляется вывод (несуществующей в таблице) колонки, являющейся арифметическим выражением над колонками данной таблицы ?

-27 -
2.В каких случаях, на Ваш взгляд, оправдано применение функции
SOUNDEX ?
3.Перечислите базовые арифметические операции и функции, используемые SQL ? Какими функциями Вы желали бы дополнить имеющийся набор ?
1.10.Вычисление функций групп строк
Групповые функции - это еще один показатель мощности SQL. Эти функции позволяют выбирать суммарную информацию из групп строк.
Предположим, что необходимо собрать всех работников с одним номером отдела в одну группу и найти максимальный оклад в каждой группе
:
SELECT DEPTNO,MAX(SAL)
FROM EMP
GROUP BY DEPTNO;
|
DEPTNO |
|
MAX(SAL) |
|
|
||
10 |
5,000.00 |
||
20 |
3,000.00 |
||
30 |
2,850.00 |
Клауза GROUP BY
В запросе GROUP BY каждая строка запроса представляет группу строк, хранимых в таблице. Имя колонки, которую назвали в клаузе GROUP BY (в данном примере DEPTNO) - это то, что нужно сгруппировать или выделить в категорию по строкам таблицы. В вышеприведенном примере каждая строка таблицы EMP была помещена в одну их трех групп, отличающихся номерами отделов - значениями поля DEPTNO, так что после того, как все строки в EMP обработаны, все строки в группе имеют один номер отдела. В этот момент выполняются групповые функции, которые были запрошены функцией MAX(SAL) над каждой группой строк и возвращаются вычисленные результаты.
Так же как с применением ORDER BY, возможно группировать любое количество колонок в единственном запросе.
Для примера скомбинируем использование групповых функций с запросом типа JOIN. Сгруппируем по двум колонкам (GROUP BY DNAME, JOB) и применим три новых функции: SUM - сложить значения выбранных полей, попавших в группу, заданную клаузой GROUP BY; COUNT(*) - подсчитать число строк, попавших в каждую группу и AVG - найти среднее арифметическое значение выбранных колонок в группе.
Целью при этом запросе является следующее узнать: сколько работников

|
|
|
|
|
|
|
- 28 - |
|
|
|
|
||
работает на каждой должности в каждом отделе; |
например, сколько клерков |
||||||||||||
в исследовательской группе, какова сумма окладов и средний оклад: |
|
||||||||||||
|
SELECT DNAME,JOB,SUM(SAL), --- функция SUM |
(**) |
|||||||||||
|
COUNT(*), --- функция COUNT(*) |
|
|
|
|
||||||||
|
AVG(SAL) --- функция AVG |
|
|
|
|
||||||||
|
FROM EMP,DEPT |
|
|
|
|
|
|
|
|
|
|||
|
WHERE EMP.DEPTNO = DEPT.DEPTNO |
|
|
|
|
||||||||
|
GROUP BY DNAME, JOB; |
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DNAME |
|
|
JOB |
|
SUM(SАL) |
|
|
COUNT(*) |
|
АVG(SAL) |
|
|
|
ACCOUNTING |
|
|
CLERC |
1,800.00 |
|
1 |
1,300.00 |
|
|
|||
|
ACCOUNTING |
|
|
MANAGER |
2,450.00 |
|
1 |
2,450.00 |
|
|
|||
|
ACCOUNTING |
|
|
PRESIDENT |
5,000.00 |
|
1 |
5,000.00 |
|
|
|||
|
RESEARCH |
|
|
ANALYST |
6,000,00 |
|
2 |
3,000.00 |
|
|
|||
|
RESEARCH |
|
|
CLERC |
1,900.00 |
|
2 |
950.00 |
|
|
|||
|
RESEARCH |
|
|
MANAGER |
2,975.00 |
|
1 |
2,975.00 |
|
|
|||
|
SALES |
|
|
CLERC |
950.00 |
|
1 |
950.00 |
|
|
|||
|
SALES |
|
|
MANAGER |
2,850.00 |
|
1 |
2,850.00 |
|
|
|||
|
SALES |
|
|
SALESMAN |
5,600.00 |
|
4 |
1,400.00 |
|
|
|||
|
Рассмотрим работу, которую выполняет программист при создании |
||||||||||||
некоторого |
вывода, если он |
|
|
применяет традиционную |
схему |
программирования. Сначала он получает список работников и сортирует его по номерам отдела и по должности. Далее суммируются число работников и средний оклад вычисляется по номерам отделов и по должности. Наконец, название отдела нужно подставить для номера отдела в выводимой информации. Каждая операция требует циклического чтения записей, сохранения промежуточных результатов, проверки ошибок и т.д.
Напротив, непроцедурный подход SQL позволяет создавать такие отчеты, как предыдущий, при помощи указания исполняющей системе только того, ЧТО необходимо сделать: исполняющая система автоматически генерирует процедуру, определяя КАКИМ ОБРАЗОМ извлечь данные таблиц.
Клауза HAVING
Ранее были определены условия поиска для индивидуальных строк при помощи клаузы WHERE; теперь можно использовать клаузу HAVING для задания условий поиска групп строк. Предположим, что необходимо получить ответ на запрос, подобный предыдущему, но при условии, что каждая группа, выводимая по запросу, должна содержать не менее двух работников:

|
|
|
|
|
|
- 29 - |
|
|
|
|
||
|
SELECT DNAME,JOB,SUM(SAL),COUNT(*),AVG(SAL) |
(***) |
||||||||||
|
FROM EMP,DEPT |
|
|
|
|
|
|
|
|
|
||
|
WHERE EMP.DEPTNO = DEPT.DEPTNO |
|
|
|
|
|||||||
|
GROUP BY DNAME,JOB |
|
|
|
|
|
|
|
||||
|
HAVING COUNT(*) >= 2; --- клауза HAVING |
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DNAME |
|
JOB |
|
SUM(SAL) |
|
|
COUNT(*) |
|
АVG(SL) |
|
|
|
RESEARCH |
|
ANALYST |
6,000.00 |
|
2 |
3,000.00 |
|
|
|||
|
RESEARCH |
|
CLERC |
1,900.00 |
|
2 |
950.00 |
|
|
|||
|
SALES |
|
SALESMAN |
5,600.00 |
|
4 |
1,400.00 |
|
|
|||
|
Условие поиска в клаузе HAVING исключает из результата |
запроса |
||||||||||
группы, содержащих менее двух работников - COUNT(*)>=2. |
|
Контрольные вопросы
1.Что такое групповые запросы к БД ?
2.Каков формат SQL-запроса с клаузами GROUP BY и HAVING ?
3.Напишите (на языке уровня Pascal или C) программы, функционально аналогичные вышеприведенным SQL-запросам (**) и (***).
2.11.Подзапросы
Одна из причин, по которым SQL столь мощен и универсален, состоит в том, что всегда можно построить сложные запросы из нескольких простых. Клауза WHERE из одного запроса может содержать другой запрос, который называется подзапросом. Можно использовать подзапросы для динамического построения условий поиска для требуемого главного запроса.
Предположим, что нужно составить список всех работников с такой же работой как у работника JONES:
SELECT ENAME,JOB --- главный запрос FROM EMP
WHERE JOB =
(SELECT JOB --- подзапрос FROM EMP
WHERE ENAME = ‘JONES’);
|
ENAME |
|
JOB |
|
|
||
|
JONES |
|
MАNАGER |
|
BLAKE |
MАNАGER |
|
|
CLARK |
|
MАNАGER |
Исполняющая система обрабатывает подзапрос перед обработкой

- 30 -
главного запроса, поскольку его результат нужен для определения результата главного запроса. Вторая команда SELECT в данном примере (а это именно подзапрос) возвращает значение MANAGER, как легко убедиться, если взглянуть на должность работника JONES в таблице EMP.
Исполняющая система использует это значение для динамического построения условия поиска WHERE JOB = 'MANAGER', используемого первой командой SELECT для возврата нужных нам строк.
Классический пример - перечислить всех работников, получающих больше среднего оклада:
SELECT ENAME,SAL FROM EMP
WHERE SAL >
(SELECT AVG(SAL) FROM EMP);
|
ENAME |
|
SAL |
|
|
||
|
JONES |
2,975.00 |
|
|
BLAKE |
2,850.00 |
|
|
CLARK |
2,450.00 |
|
|
SCOTT |
3,000.00 |
|
|
KING |
5,000.00 |
|
|
FORD |
3,000.00 |
Подзапросы могут тоже быть составными, как и основные запросы - они могут содержать условия поиска и запросы JOIN. Например, можно использовать их в командах INSERT, UPDATE и DELETE (рассматриваемых
вследующих секциях) наряду с командами SELECT.
Контрольные вопросы
1.В чем заключается удобство использования подзапросов в SQL-клаузе
SELECT ?
2.Каков порядок выполнения подзапросов и каким образом его можно изменить ?
3.Составьте SQL-предписание для уничтожения строк с информацией о работниках, имеющих оклад не выше 25% от среднего. Каковы ‘подводные камни’, могущие возникнуть при выполнении этой операции ?
2.12.Модификация хранимых данных
Как видно из вышеизложенного, одна команда SELECT позволяет выбрать набор строк из одной или нескольких таблиц. SQL позволяет