Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Технология проектирования и администрирования баз данных и систем данных-Конспект3

.pdf
Скачиваний:
33
Добавлен:
20.03.2016
Размер:
1.05 Mб
Скачать

- 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 позволяет