МГАПИ
МОСКОВСКАЯ ГОСУДАРСТВЕННАЯ АКАДЕМИЯ ПРИБОРОСТРОЕНИЯ И ИНФОРМАТИКИ
Кафедра ‘Персональные компьютеры и сети’
В.М...
43 downloads
286 Views
668KB Size
Report
This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Report copyright / DMCA form
МГАПИ
МОСКОВСКАЯ ГОСУДАРСТВЕННАЯ АКАДЕМИЯ ПРИБОРОСТРОЕНИЯ И ИНФОРМАТИКИ
Кафедра ‘Персональные компьютеры и сети’
В.М.Баканов
Введение в язык SQL запросов к базам данных
Москва 2002
-2-
УДК 681.3 Введение в язык SQL запросов к базам данных. Учебное пособие / В.М.Баканов. -М.: МГАПИ, 2002. -61 c.: ил. ISBN 5-8068-0243-4 Рекомендовано Ученым Советом МГАПИ в качестве учебного пособия для специальности 2201. Рецензенты: профессор, д.т.н. профессор
Ивченко В.Д. Зеленко Г.В.
Предлагаемое издание рекомендуется в качестве учебного пособия для дисциплины ‘Базы данных’ специальности 2201 и смежным специальностям, для которых данная дисциплина не является профилирующей. В пособии изложены основные вопросы, связанные с использование языка SQL доступа к базам данных. Изложены основы применения структурированного языка программирования запросов SQL (Structured Query Language) и практической работы в системах Delphi / C++Builder (выбраны как удобные, распространенные и недорогие системы Windowsпрограммирования, поддерживающие практически все известные форматы баз данных). Освоение разработчиками Delphi / C++Builder операционной системы Linux (RAD-система Kylix, подробнее см. http://www.borland.ru/kylix/index.html) еще более повышает ценность накопленных при работе с Delphi / С++Builder навыков программирования. Рассмотрены практические примеры создания SQL-ориентированных приложений для работы с базами данных. В состав пособия входит программное обеспечение (SQL-тренажеры (выгрузка доступна без ограничений с WEB - адреса http://pilger.mgapi.edu/bin/sql_test.zip, файл содержит инсталляцию для всех версий Windows, объем 2,1 Mb); рекомендуется изучение пособия синхронно с работой на ПЭВМ с вышеуказанным программным обеспечением. Последняя версия данного методического пособия может быть получена в виде файла http://pilger.mgapi.edu/metods/sql.zip.
Л
1402010000 ЛР020418 − 97
ISBN 5-8068-0243-4
© В.М.Баканов, 2002
-3-
СОДЕРЖАНИЕ Стр. ВВЕДЕНИЕ.............................................................................................. 1.ИСПОЛЬЗОВАНИЕ SQL..................................................................... 1.1.Пример базы данных...................................................................... 1.2.Выбор данных из таблиц................................................................ 1.3.Создание и уничтожение таблиц.................................................... 1.4.Введение строк в таблицы.............................................................. 1.5.Выбор заданных строк и колонок из таблиц................................. 1.6.Упорядочение строк по запросу.................................................... 1.7.Предохранение от выбора строк-дубликатов................................ 1.8.Запросы к нескольким таблицам.................................................... 1.9.Арифметические операции и функции строк символов................ 1.10.Вычисление функций групп строк............................................. 1.11.Подзапросы................................................................................... 1.12.Модификация хранимых данных.................................................. 1.12.1.Команда UPDATE.................................................................. 1.12.2.Команда INSERT.................................................................... 1.12.3.Команда DELETE................................................................... 1.13.Динамические изменения структуры базы данных...................... 1.14.Альтернативные виды данных...................................................... 1.15.Независимость данных................................................................. 1.16.Разделение данных и защита......................................................... 1.17.Понятие транзакции...................................................................... 1.18.Понятие триггера.......................................................................... 2.ПРАКТИЧЕСКОЕ ИСПОЛЬЗОВАНИЕ SQL НА ПЭВМ.................... 2.1.Создание приложений класса баз данных в Delphi / С++Builder.......................................................................... 2.2.Использование тренажера локального SQL................................... 2.2.1. Тренажер SQL-запросов к одной таблице.............................. 2.2.2.Тренажер SQL-запросов к двум таблицам.............................. 2.2.З.Утилита dbEXPLORER разработки АО ROSNO..................... 2.3.Дополнительные инструментальные средства пакетов Delphi/C++Builder............................................................................ ЗАКЛЮЧЕНИЕ....................................................................................... СПИСОК ЛИТЕРАТУРЫ.......................................................................
-4-
ВВЕДЕНИЕ Язык запросов SQL был предложен корпорацией IBM в 70-х годах. Первоначально были созданы два основных продукта на основе SQL - DB2 и SQL/DS; далее на базе операционной системы 0S/2 предложена система Database Manager [1,2]. С тех пор язык SQL был принят большинством фирм, поставляющих на рынок базы данных как для персональных, так и для 'больших' (MAINFRAME) ЭВМ и стал фактическим стандартом получения информации из реляционных баз данных. Со времени создания SQL четко обособились фактически две ветви в разработке систем для управления базами данных - на основе непроцедурного языка SQL и процедурных языков (язык dBase, Paradox, Clarion и многие другие). Фактически каждый из процедурных языков БД представляет некоторый 'надъязык' (по отношению к уровню Fortran, Pascal, С), ориентированный на обработку записей БД. Совсем другой подход реализован в SQL - создан непроцедурный язык запросов к БД, в полной мере реализующий принцип DWIM - 'Делай то, что я имею в виду !'. При пользовании SQL пользователь на формальном языке запрашивает некоторую операцию (например, выборку из одной или более баз), а интерпретирующая SQL-система выполняет задание. Заметим, что при пользовании процедурным языком пришлось бы (с большей или меньшей степенью детализации) описать все (возможно, очень многие) необходимые действия. Таким образом, одна фраза на SQL может быть равноценна целым страницам инструкций на языках уровня С, Pascal, Fortran и др. Однако подобные возможности языка SQL требуют значительных аппаратных ресурсов ЭВМ (соответствующей мощности процессора и многомегабайтной оперативной памяти для интерпретации и выполнения SQL-предложений); таким образом системы на основе SQL оправданы при реализации серьезных приложений (банковские системы, региональные и глобальные БД etc) В настоящее время поддержка SQL-команд встроена в dBase, Borland Delphi / C++Builder, SQL Windows, PowerBuilder и другие системы. SQL является обычным для обеспечения работы с БД в сети InterNet - например, расширение MySQL (www.mysql.com) для языков Perl (www.perl.com, www.cpan.org) и PHP (www.php.net, www.phpclub.net), входящий в пакет Java.sql интерфейс JDBC (Java DataBase Connectivity) фирмы JavaSoft для языка Java. Однако SQL (как и многие другие непроцедурные языки) не содержит ряда привычных программистам возможностей - таких, как использование условных выражений и организации циклов. По этим соображениям команды SQL часто встраиваются в процедурные языки программирования, например, в С/C++ и др.
-5-
Язык SQL ориентирован на операции с данными, представленными в виде логически связанной совокупности таблиц в отличие от процедурных БД-языков, ориентированных на операции с данными, представленными в виде записей. SQL-язык естественно вошел в современную идеологию систем распределенной обработки данных типа 'клиент-сервер', где SQL-предписания приложениемгенерируются приложением-клиентом и выполняются сервером (обычно использующим значительные мощности машинысервера). При этом удается значительно уменьшить сетевой трафик (поток информации): от клиента к серверу идет небольшой поток данных в виде SQL-команд, обратный поток также невелик и состоит из логически обработанной согласно SQL-предписаниям относительно небольшой части общей БД; причем реализация хранимых процедур позволяет вообще вынести выполнение наиболее часто используемых SQL-процедур с клиента на сервер и тем самым еще более разгрузить клиент-приложение и клиент-машину. Из реализующих подобный подход инструментальных систем следует назвать SQLBase, SQLWindows (фирма GUPTA Corp.), EasyCASE (Evergreen Tools, Inc.), PowerBuilder (PowerSoft), SyBase и InterBase, Delphi и C++Builder (Borland Int.) и другие. Внедрение клиент-серверных технологий в бывшем СССР значительно отстало от мирового уровня еще и из-за того, что мощные современные приложения-серверы применялись в армии США, что автоматически накладывало ограничения на их использование в странах Восточного блока (это относится, например, к мощному серверу Borland InterBase). Важной причиной использования SQL является совместимость, являющаяся следствием фактического стандарта SQL (в настоящее время существуют стандарты ANSI - Американского национального института стандартов и стандарт корпорации IBM). Конечно, не все реализации поддерживают полные возможности SQL; пожалуй, наиболее полно и последовательно стандарт SQL реализован в программном продукте корпорации ORACLE (Oracle Corporation, Belmont, California, USA) и в сервере InterBase (Borland Int). Стандарт SQL является совместной разработкой ANSI (American National Standards Institute) и ISO (International Organization for Standardization), в 1986 году опубликовавших серию стандартов SQL/86. Первый международный стандарт языка SQL был принят в 1989 году (стандарт SQL/89) и устанавливал многие важные свойства языка как определяемые реализацией (что дало большой простор для расхождений между различными реализациями SQL, причем многие аспекты языка вообще не упоминались в SQL/89). В 1992 году принят новый стандарт языка - SQL/92, известны стандарты SQL/99 и SQL/J (расширение SQL для Java). Сказанное фактически констатирует определенное разнообразие реализации языка SQL в сущест-
-6-
вующих системах. Заметим, что язык SQL разработан для работы с реляционными базами данных (РБД) и фактически представляет собой систему управления реляционными базами данных (СУРБД). Для информации в нижерасположенной таблице представлены основные логические модели БД с указанием достоинств и недостатков каждой из них. Логические структуры баз данных Логическая структура Иерархическая модель
Достоинство
Представление структур данных в виде дерева практически не ограничивает сложность логических связей между порциями данных Сетевая модель Представление данных в виде произвольного графа позволяет представлять структуру данных любой сложности Реляционная Представление структур данных модель в виде совокупности связанных отношениями (relation) таблиц весьма наглядно и удобно для реализации обработки данных ОбъектноЗаключающийся в объединении ориентирован- данных и функций для их обраная модель ботки в единое целое синтез особенностей сетевой и реляционной моделей и объектной технологии выгоден при создании высокоструктурированных БД
Недостаток Чрезмерная громоздкость при описании данных со сложными логическими связями Сложность реализации
Представление сложных структур требует большого количества связанных таблиц большинства Для приложений класса БД объектноориентированный подход неоправданно сложен
Реляционные системы берут свое начало в математической теории множеств. Они были предложены в конце 1968 года доктором Э.Ф.Коддом из фирмы IBM, который впервые осознал, что можно использовать математику для придания надежной основы и строгости в области управления базами данных. РБД можно определить как БД, которая представляется пользователю набором связанных между собой таблиц и ничем кроме таблиц. Над таблицами определены операции - проекции, соединения и др. Говорят, что база данных представлена в первой, второй, третьей нормальной форме и
-7-
нормальной форме Бойса-Кодда, если она удовлетворяет определенным требованиям [2...4]. Некоторые авторы считают, что первая нормальная форма 1НФ (требующая, чтобы всякий столбец в любой таблице являлся 'атомным’, то есть единственным, неделимым, а не списком) является предпосылкой того, что БД является реляционной. Более изощренные определения РБД можно найти, например, в книге [5]. Сам Э.Ф.Кодд в 1985 г. опубликовал 12 правил, которым должна удовлетворять любая БД, претендующая на звание реляционной. Однако можно сформулировать более простое (и тем не менее достаточно функциональное) определение РБД - 'Реляционной называется база данных, в которой все данные, доступные пользователю, организованы в виде таблиц, а все операции над данными сводятся к операциям над этими таблицами'. С реляционной моделью данных связаны понятия ключа и индекса. Ключи предназначены для идентификации записей в таблице; простой ключ состоит из одного поля, а составной ключ - из комбинации полей (поля, по которым построен ключ, именуются ключевыми). В таблице может быть определен только один первичный ключ, который используется для ускорения выполнения запросов к БД; при выполнении запроса на поиск записи благодаря упорядочиванию значений ключа реализуется непосредственный доступ к нужной записи без (последовательного) просмотра всей таблицы. Поле индекса строится по полям таблицы, но в отличие от ключа, индекс может допускать повторение значений составляющих его полей. Простой индекс включает одно, составной индекс - несколько полей; индексы при их создании именуются. Главное назначение индексирования - ускорение процесса поиска записей по значению одного (или нескольких) полей. Организация связи (отношений) между таблицами (двумя или несколькими) называется связыванием или соединением таблиц; для связывания таблиц используются поля связи, которые должны быть индексированными. Связь между таблицами определяет отношение подчиненности, при котором одна таблица является главной (родительской, или мастером - Master), а вторая - подчиненной (дочерней, детальной - Detail). Между таблицами возможны следующие виды отношений: • ‘один-к-одному’ (записывается как ‘1:1’); • ‘один-ко-многим’ (записывается как ‘1:n’); • ‘много-к-одному’ (записывается как ‘n:1’); • ‘много-ко-многим (записывается как ‘m:n’)’. Отношение ‘один-к-одному’ означает, что записи главной таблицы сопоставлена одна запись в подчиненной таблице, отношение ‘один-ко-многим’ (встречается наиболее часто) отражает факт соответствия нескольких записей подчиненной таблицы одной записи главной таблицы, отношение ‘много-к-
-8-
одному’ равносильно предыдущему при взгляде со стороны подчиненной таблицы; отношение ‘много-ко-многим’ на практике встречается достаточно редко. В SQL определены внешние (foreign) и родительские (parent) ключи, обеспечивающие необходимую связь между таблицами БД и поддерживающие ссылочную целостность. Вопросы использования внешних и родительских ключей для поддержания ссылочной целостности БД непросты и не рассматриваются в данном пособии, рекомендуются работы [1,2]. Принятый в настоящее время подход к проектированию БД основан на модели типа ‘сущность - связь’ (Entity-Relationship model, ER) и был предложен в 1970-х годах Питером Ченом (Peter Chen). Существует достаточное количество программных продуктов, позволяющих (часто в графическом режиме) проектировать сложные БД (устанавливать связи между таблицами, генерировать необходимые SQL-запросы и др.); одним из известных подобных CASE-систем является, например, пакет ERwin (см. работу [7] и др.) В последние годы появляются утверждения о недостаточной эффективности SQL при создании корпоративных распределенных информационных систем и необходимости перехода к более гибким системам типа TUXEDO System, TEKNETRON и др. [8]; однако SQL нашел свою нишу и, похоже, прижился прочно и надолго. При практическом применении используются Windowsориентированные системы программирования Delphi и/или C++Builder для IBM PC. Системы установлены на ПЭВМ и доступны пользователю в диалоговом режиме. Целью работы является ознакомление на практике с возможностями применения языка SQL для реализации разнообразных запросов к БД и их (запросов) возможной оптимизации. Синтаксис SQL дан (в некоторых случаях) применительно к стандарту Oracle как наиболее полно реализующему возможности SQL; практическая работа ведется в среде систем Delphi или C++Builder. Предполагается предварительное изучение литературы по теории и практике работы БД и знакомство с основами работы на IBM PCсовместимых ПЭВМ. 1. ИСПОЛЬЗОВАНИЕ SQL Существуют три формы SQL: интерактивный (Interactive), статический (Static) и динамический (Dynamic). Функционируют они одинаково, но используются по-разному. • Интерактивный SQL применяется для непосредственной работы с БД пользователь вводит SQL-оператор, он сразу же выполняется и пользова-
-9-
тель видит результат выполнения (или код ошибки). • Статический SQL содержит SQL-операторы, жестко закодированные в теле исполняемого приложения. Наиболее распространен встроенный SQL (Embedded SQL), где SQL-код включается в исходный текст (базовой) программы, написанной на другом языке (например, С или Pascal); при использовании встроенного SQL результаты выполнения операторов SQL перенаправляются в переменные, которыми оперирует базовая программа. К настоящему времени SQL встроен в языки Ada, Cobol, Fortran, C, Pascal, PL/1, Java, Mumps (теперь M). • Динамический SQL также является частью приложения, но конкретный SQL-код генерируется во время выполнения (Run Time), а не вводится заранее. Фактически везде ниже описывается интерактивная форма SQL - сначала приводится текст SQL-запроса, а ниже дается ответ исполняющей системы (обычно в виде таблицы). Нижеприведенные примеры показывают базовые концепции реляционной базы данных и обеспечивает последовательность задач, демонстрирующих мощь языка SQL. Начнем с основных действий над таблицами базы данных: • SELECT - выборка строк из таблиц • CREATE - создание таблицы • INSERT - ввод строки в таблицу 1.1.Пример базы данных Базы данных в терминологии SQL состоят из таблиц. К понятию таблицы наиболее близок аналог файла таких БД, как dBase, Clarion etc и состоит из некоторого количества строк (аналог ЗАПИСЕЙ, если пользоваться терминологией не-SQL языков); причем системы Delphi / С++Builder поддерживают множество форматов файлов таблиц, что, однако, практически никак не отражается на использование SQL. Запомним это: неважен тип СУБД - был бы реализован язык SQL. Большинство нижеследующих примеров будет использовать DEPT таблицу, содержащую информацию об отделах компании, и таблицу ЕМР, содержащую информацию о работниках данной компании. Таблица DEPT DEPTNO (код отдела)
DNAME (название отдела)
LOC (место расположения)
- 10 -
10 20 30 40
ACCOUNTIG RESEARCH SALES OPERATIONS
NEW YORK DALLAS CHICAGO BOSTON
Таблица ЕМР EMPNO
ENAME
JOB
(таб. номер) 7369 7499 7521 7566 7654 7698 7782 7788 7839 7844 7876 7900 7902 7934
(имя)
(должность) CLERK SALESMAN SALESMAN MANAGER SALESMAN MANAGER MANAGER ANALYST PRESIDENT SALESMAN CLERK CLERK ANALYST CLERK
SMITH ALLEN WARD JONES MARTIN BLAKE CLARK SCOTT KING TURNER ADAMS JAMES FORD MILLER
MGR
7902 7698 7698 7839 7698 7839 7839 7566 7698 7788 7698 7566 7782
HIREDATE (дата приема на работу) 17-DEC-80 20-FEB-81 22-FEB-81 02-APR-81 28-SEP-81 01-MAY-81 09-JUN-81 09-NOV-81 17-NOV-81 08-SEP-81 23-SEP-81 03-DEC-81 03-DEC-81 23-JAN-82
SAL (оклад) 8,00.00 1,600.00 1,250.00 2,975.00 1,250.00 2,850.00 2,450.00 3,000.00 5,000.00 1,500.00 1,100.00 950.00 3,000.00 1,300.00
COMM DEPTNO (комиссион(отдел) ные) 20 300.0 30 500.0 30 20 1,400.0 30 30 10 20 10 30 20 30 20 10
Каждая таблица состоит из колонок (вертикальных) и строк (горизонтальных). Таблица DEPT имеет три колонки (называемые DEPTNO, DNAME и LOC) и 4 строки (одна для каждого отдела номер 10,20,30,40). Строка состоит из полей. Каждое поле содержит значение данных на пересечении строки и колонки. Например, в первой строке таблицы DEPT значение 10 хранится в поле DEPTNO, значение ACCOUNTING хранится в поле DNAME, значение NEW YORK - в поле LOC. Легко заметить, что все таблицы примера (как и все таблицы любой реляционной базы данных) состоят из строки заголовков столбцов и одной или более строк значений данных под этими заголовками. Эти столбцы и строки должны обладать следующими свойствами: • всякий столбец таблицы обладает в этой таблице уникальным именем; • столбцы таблицы упорядочиваются слева направо, т.е. столбец 1, столбец 2, ... столбец n. C точки зрения пользователя порядок, в котором определены имена столбцов, становится порядком, в котором должны вводиться в них данные, если не предварять при вводе каждое значение именем соответствующего столбца;
- 11 -
• строки таблицы не упорядочены (их последовательность определяется лишь последовательностью ввода в таблицу); • в поле на пересечении строки и столбца любой таблицы всегда имеется в точности одно значение данных и никогда не должно быть множества значений (правда, это 'атомарное' значение может быть достаточно объемным, например, таким, как рецепт некоего блюда или много мегабайтный мультимедиа-файл); • всем строкам таблицы соответствует одно и то же множество столбцов, хотя в определенных столбцах любая строка может содержать пустые значения (NULL-значения), т.е. может не иметь значений для этих столбцов; • все строки таблицы обязательно отличаются друг от друга хотя бы единственным значением, что позволяет однозначно идентифицировать любую строку такой таблицы; • при выполнении операций с таблицей ее строки и столбцы можно обрабатывать в любом порядке безотносительно к их информационному содержанию. База данных, состоящая из таких таблиц, называется реляционной. Отношение (RELATION) - является математическим термином для обозначения неупорядоченной совокупности однотипных записей или таблиц определенного специфического вида, описанного выше. Таким образом, можно, например, сказать, что определенная база данных состоит минимум из стольких отношений, сколько отдельных таблиц она включает. Нечеткость многих терминов, используемых в сфере обработки данных, заставила Э.Ф.Кодда отказаться от них и предложить новые или дать более точные определения существующим. Так, он не мог использовать широко распространенный термин 'ЗАПИСЬ', который в различных ситуациях может означать экземпляр записи, либо тип записей, запись в стиле Кобола (которая допускает повторяющиеся группы) или плоскую запись (которая их не допускает), логическую запись или физическую, запись, хранимую запись или виртуальную запись и т.д. Вместо этого он использовал термин 'кортеж длины N' или просто 'кортеж', которому дал точное определение. В основополагающих работах [4,5] можно подробно познакомиться с терминологией реляционных баз данных (есть русскоязычные переводы), здесь же будем использовать неформальные их эквиваленты: таблица строка (или запись) столбец (или поле)
- для отношения - для кортежа - для атрибута
Заметим также, по определению принимается, что 'запись' означает 'э-
- 12 -
кземпляр записи', а 'поле' означает 'имя и тип поля'. Контрольные вопросы 1. Какие основные логические структуры БД применяются в настоящее время? 2. Что такое реляционная БД? 3. Что такое таблица реляционной БД и из чего состоит таблица? 4. Какие типы отношений возможны между таблицами? 5. В чем заключается универсальность языка SQL перед специализированными языками работы с БД? 6. Каковы основные свойства строк и столбцов реляционной БД? 7. Чем отличаются интерактивная, статическая и динамическая форма применения языка SQL? 8. Какие основные действия над таблицами определены в языке SQL? 1.2.Выбор данных из таблиц. Команда SELECT Выборка данных из БД является наиболее распространенной операцией SQL. Обращение к базе данных называется запросом и для его реализации необходимо использовать команду SELECT. Базовая команда (предписание) SELECT состоит из двух частей, носящих названия клауз (clause): SELECT некоторые данные (имя (имена) колонки) FROM таблица или некоторые таблицы (имя (имена) таблицы) ; Клауза SELECT всегда вводится первой, а за ней следует клауза FROM. Вывод запрошенной информации в данном случае (спецификация вывода не определена) осуществляется на экран дисплея. Рассмотрим выборку данных в таблицах DEPT и ЕМР, используя некоторые простые запросы SQL. Простейший пример - вывести все строки и колонки таблицы DEPT. Команды SQL, обеспечивающие этот запросы, следующие (строки после последовательности дефисов являются комментарием, не входят в исходный текст и не должны вводиться в диалоге): SELECT DEPTNO,DNAME,LOC --- вводит пользователь ! FROM DEPT; ---то же... DEPTNO 10 20 30
DNAME ACCOUNTIG RESEARCH SALES
LOC NEW YORK DALLAS CHICAGO
- 13 -
40
OPERATIONS
BOSTON
SELECT-запрос возвращает значение (в отличие от других, описанных ниже, SQL-предписаний). Обычно SQL-запрос возвращает множество строк (в частном случае ни одной), причем указатель (обычно реализованный в виде стрелки или цветовой подсветки определенной строки) в каждый момент указывает на одну из них. В вышеприведенном примере запроса были перечислены имена всех колонок таблицы DEPT (а именно DEPTNO, DNAME, LOC) в клаузе SELECT. Обычно при задании всех колонок можно использовать звездочку (*) как сокращение списка имен: SELECT * FROM EMP; --- конец команды EMPNO 7369 7499 7521 7566 7654 7698 7782 7788 7839 7844 7876 7900 7902 7934
ENAME SMITH ALLEN WARD JONES MARTIN BLAKE CLARK SCOTT KING TURNER ADAMS JAMES FORD MILLER
JOB CLERK SALESMAN SALESMAN MANAGER SALESMAN MANAGER MANAGER ANALYST PRESIDENT SALESMAN CLERK CLERK ANALYST CLERK
MGR 7902 7698 7698 7839 7698 7839 7839 7566 7698 7788 7698 7566 7782
HIREDATE 17-DEC-80 20-FEB-81 22-FEB-81 02-APR-81 28-SEP-81 01-MAY-81 09-JUN-81 09-NOV-81 17-NOV-81 08-SEP-81 23-SEP-81 03-DEC-81 03-DEC-81 23-JAN-82
SAL 8,00.00 1,600.00 1,250.00 2,975.00 1,250.00 2,850.00 2,450.00 3,000.00 5,000.00 1,500.00 1,100.00 950.00 3,000.00 1,300.00
COMM 300.00 500.00 1,400.00
DEPTNO 20 30 30 20 30 30 10 20 10 30 20 30 20 10
Для удобства восприятия текста часто разделяют большинство команд SQL на несколько строк и печатают их большими буквами для простоты чтения. Однако, при желании, можно набирать команды и в одной строке большими или маленькими буквами. Конец отдельной команды SQL идентифицируется точкой с запятой. Когда интерпретирующая SQL система обнаружит ее, он запустит команду на исполнение (интерпретацию). В некоторых системах (в том числе Delphi / C++Builder) точка с запятой необязательна. SELECT-запрос возвращает некоторое множество (возможно, пустое) строк, именуемое курсором. Возникает естественный вопрос - кто 'принимает' это значение (с целью последующей обработки) в прикладной программе? Для связи SQL с пользовательской программой (написанной на конкретном языке программирования) используется клауза INTO:
- 14 -
SELECT некоторые данные (имя (имена) колонки) INTO куда копировать возвращаемые SELECT’ом данные FROM таблица или некоторые таблицы (имя (имена) таблицы) ; Часто используемая клауза FETCH используется для выборки первой записи курсора, присвоения значений столбцов этой записи переменным, перечисленным в клаузе INTO, и перемещения указателя на следующую строку курсора. Таким образом, последовательно применяя FETCH, можно запомнить значение любой записи из возвращенных по запросу. Во многих системах программирования имеются ‘родные’ функции, по функциональности аналогичные FETCH. Кроме того, в реальной исполняющей системе каждое SQL-предписание возвращает код окончания операции (в переменной SQLCODE, для Fortran’а - SQLCOD); причем нулевое значение этой системной переменной информирует о успешности выполнения SQL-предписания, положительное - о возникновении некоторой исключительной ситуации, отрицательное о невозможности выполнения запроса. В стандарте SQL/92 введена (предпочтительная) строковая переменная SQLSTATE, для Fortran’а - SQLSTA) из 5ти символов, причем первые 2 символа - дают общую информацию (class) об ошибке, следующие 3 символа (subclass) уточняют описание. Контрольные вопросы 1. Какие клаузы используются при составлении команды SELECT выбора данных из таблицы? 2. Возвращает ли предписание SELECT значение в вызывающую программу? 3. Каким образом можно проанализировать возвращаемое SQL-предписанием значение и проверить успешность выполнения команды? 4. Что такое курсор в понятиях языка SQL? 5. Каким образом записываются комментарии в предписаниях SQL? 1.3.Создание и уничтожение таблиц Команда CREATE TABLE Перед тем как выбрать данные из базы данных, их нужно в нее ввести, а перед этим нужно создать таблицу, в которой эти данные будут храниться. Ниже приведен пример команды SQL для создания таблицы DEPT : CREATE TABLE DEPT (DEPTNO DNAME
NUMBER (2), CHAR (14),
- 15 -
LOC
CHAR (13));
В команде CREATE TABLE сначала сообщается, как назвать таблицу (DEPT). Далее задаются имена колонок (полей) таблицы (DEPTNO, DNAME, LOC) и тип данных, которые каждая колонка содержит. В создании данной таблицы, например, определяется, что колонка DEPTNO содержит только цифровые данные (NUMBER), а колонки DNAME и LOC любые символьные данные (CHAR) - буквы, числа или знаки пунктуации. Наконец, следует задать максимальную длину любого значения, которое можно хранить в колонках. Например, в команде CREATE TABLE, приведенной выше, задано, что длина имени места расположения (LOC) не должна быть длиннее 13 символов. Для создания таблицы ЕМР требуется следующая инструкция SQL: CREATE TABLE EMP (EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
NUMBER (4) NOT NULL, CHAR (10), CHAR (9), NUMBER(4), DATE, --- тип DATE NUMBER(7,2), NUMBER(7,2), NUMBER(2));
Таблица создается как файл с заданным конструкцией CREATE TABLE именем и расширением, определяемым текущей программной средой (например, файлы таблиц в формате dBase имеют расширение DBF, в формате Paradox - DB). Имя файла ключа состоит из имени ключа и фиксированного расширения (например, MDX для формата dBase). В то же время мощные СУБД хранят все таблицы в одном файле, имя которого совпадает с именем базы данных (расширение ORA для ORACLE или GDB для InterBase). Месторасположения создаваемого файла определяется алиасом (псевдонимом), представляющим собой (обычно короткую) строку, в соответствие которой ставится полный путь по каталогам файловой системы (настройка алиаса производится разработчиком и часто уточняется во время инсталляции приложения). В данной команде CREATE TABLE определена колонка EMPNO таблицы ЕМР как непустая (квалификатор NOT NULL). Это значит, что каждая строка таблицы ЕМР должна содержать значение в поле EMPNO (исполняющая система не позволит ввести строку без этого значения). Другими словами, отсутствующие значения (называемые пустыми) НЕ допускаются в этой колонке. Спецификация SQL-языка NOT NULL является одним из простейших примеров того, как исполняющая система проверяет значения данных при их вводе в базу данных, чтобы убедиться, что они соответствуют заданным
- 16 -
условиям целостности. Далее будет пояснено, как потребовать уникальности значений в колонке. Спецификация UNIQUE будет автоматически запрещать ввод строки со значением, которое уже имеется в БД. Колонка под названием HIREDATE определена для хранения дат. В некоторых системах дата (и время) хранится в длинном целом. Колонки оклад (SAL) и комиссионные (COMM) определены как цифровые данные (NUMBER) с максимальной длиной в 7 цифр, две из которых находятся справа от десятичной точки. Инструкция CREATE также используется для создания индексов таблиц. Несмотря на то, что ANSI-стандарт в настоящее время практически не поддерживает средства индексирования, они весьма полезны и широко используются на практике; подробнее об индексации таблиц см. работу [1]. Уничтожение таблиц Для уничтожения таблицы служит предписание DROP, две нижеследующие команды уничтожают таблицы EMP и DEPT: DROP TABLE EMP; DROP TABLE DEPT;
Инструкция DROP также применяется для уничтожения индексов таблицы. Контрольные вопросы 1. Какое SQL-предписание используется для создания таблиц и их индекирования? 2. Какие основные типы данных используются при создании и дальнейшей работы с таблицами? 3. Как располагаются таблицы БД в реальных файлах? 4. Что такое алиас и каким путем он определяется? 5. Каким образом определяется обязательность наличия и уникальность данных в строках таблицы? 6. Какие предписания применяются для определения системных данных (например, типа ‘дата’)? 7. Каков формат SQL-команд для уничтожения таблиц и индексов таблиц? 1.4.Введение строк в таблицу Для введения строк в таблицу служит SQL-предписание INSERT, именно так заполняются таблицы:
- 17 -
INSERT INTO DEPT VALUES (10, 'ACCOUNTING', 'NEW YORK'); INSERT INTO DEPT VALUES (20, RESEARCH’, ‘DALLAS'); INSERT INTO DEPT VALUES (30, 'SALES', 'CHICAGO'); INSERT INTO DEPT VALUES (40, 'OPERATIONS', 'BOSTON');
Эти четыре инструкции SQL как раз и заполняют приведенную выше таблицу DEPT. Контрольные вопросы 1. Каков формат SQL-предписания для внесения данных в таблицу? 2. Каким путем определяется, что внесенные в таблицу данные являются строковыми? 1.5.Выбор заданных колонок и строк из таблиц Выбор конкретной колонки Ранее был приведен пример выбора всех колонок и всех строк из таблицы. Для выбора нужных пользователю колонок таблицы следует ввести в клаузу SELECT имена только тех колонок, которые действительно необходимы: SELECT DNAME, DEPTNO FROM DEPT; DNAME ACCOUNTIG RESEARCH SALES OPERATIONS
DEPTNO 10 20 30 40
Результат этого запроса - сама таблица, состоящая из колонок и строк. Порядок, в котором перечислены колонки в клаузе SELECT, управляет порядком колонок в полученной таблице. Если задать SELECT *, то последовательность появления колонок соответствует исходной. Выбор заданных строк Из последнего примера видно, как клауза SELECT позволяет выбрать из таблицы заданные колонки. Но для выбора заданных строк нужно ввести в команду SELECT клаузу WHERE: SELECT *
- 18 -
FROM EMP WHERE DEPTNO = 30; --- пример клаузы WHERE EMPNO 7499 7521 7654 7698 7844 7900
ENAME ALLEN WARD MARTIN BLAKE TURNER JAMES
JOB SALESMAN SALESMAN SALESMAN MANAGER SALESMAN CLERK
MGR 7698 7698 7698 7839 7698 7698
HIREDATE 20-FEB-81 22-FEB-81 28-SEP-81 01-MAY-81 08-SEP-81 03-DEC-81
SAL 1,600.00 1,250.00 1,250.00 2,850.00 1,500.00 950.00
COMM 300.00 500.00 1,400.00
DEPTNO 30 30 30 30 30 30
Клауза WHERE заставляет искать данные в таблице и выводить только те строки, которые удовлетворяют условиям поиска. В примере выше будут возвращены только те строки, где номер отдела работника был равен 30 (WHERE DEPTNO = 30). Сложные (комбинированные) условия поиска Иногда необходимо задать несколько условий поиска в клаузе WHERE. Предположим, например, что необходимо иметь список менеджеров компании с окладом более 2800 долларов: SELECT ENAME,JOB,SAL FROM EMP WHERE JOB = 'MANAGER' AND SAL > 2800; --- логическая связка AND ENAME JONES BLAKE
JOB MANAGER MANAGER
SAL 2,975.00 2,850.00
Несколько условий поиска объединены здесь словом ключевым AND (И) (JOB='MANAGER' AND SAL>2800). Соединитель AND означает, что данные должны удовлетворять обоим перечисленным условиям поиска. Можно соединять по AND любое число условий. Альтернативные условия поиска В дополнение к возможности выбирать строки, соответствующие всем условиям, можно выбирать и строки, соответствующие любому из нескольких условий: SELECT ENAME, JOB,SAL FROM EMP WHERE JOB = 'MANAGER'
- 19 -
OR SAL > 2800; --- логическая связка OR ENAME JONES BLAKE SCOTT KING FORD
JOB MANAGER MANAGER ANALYST PRESIDENT ANALYST
SAL 2,975.00 2,850.00 3,000.00 5,000.00 3,000.00
В этом примере соединяются условия поиска словом OR (ИЛИ) (JOB='MANAGER' OR SAL > 2800). Логическая связка OR значит, что если данные удовлетворяют одному из нескольких условий, то они будут выбраны. Отрицательные условия поиска Можно выбирать строки, не удовлетворяющие данному условию. Например, несложно выбрать всех менеджеров, которые не работают в отделе 30: SELECT ENAME,JOB,DEPTNO FROM EMP WHERE JOB = 'MANAGER' AND DEPTNO != 30; --- пример НЕ РАВНО ENAME JONES CLARK
JOB MANAGER MANAGER
DEPTNO 20 10
Можно комбинировать AND, OR и NOT в одном запросе, чтобы выбрать нужную информацию; для достижения нужного результата следует применять скобки. Поиск в диапазоне Оператор BETWEEN позволяет выбирать строки в заданном диапазоне (включая границы оного). Например, перечислим всех работников, оклад которых находится между 1200 и 1400 долларами: SELECT ENAME,SAL FROM EMP WHERE SAL BETWEEN 1200 AND 1400;
- 20 -
ENAME WARD MARTIN MILLER
SAL 1,250.00 1,250.00 1,300.00
Поиск значений в списке Предписание IN дает возможность выбрать строки, содержащие заданные значения. Перечислим все отделы, номера которых 10 или 30: SELECT * FROM DEPT WHERE DEPTNO IN (10,30); --- только 10 или 30 DEPTNO 10 30
DNAME ACCOUNTIG SALES
LOC NEW YORK CHICAGO
Отметим, что следует заключить список значений в скобки - (10,30). Для этого запроса возможно было применить логическую связку OR для получения того же самого результата (WHERE DEPTNO=10 OR DEPTNO=30). Последовательности сопоставления символов Можно также выбрать строки, соответствующие образцу символов или цифр, который задается после клаузы LIKE. Например, перечислим всех работников, имеющих в имени символ ‘R’ в третьей от начала позиции: SELECT ENAME FROM EMP WHERE ENAME LIKE ‘__R%’; ENAME WARD MARTIN TURNER FORD
В это примере используется оператор LIKE для указания выбрать все строки из таблицы EMP, в которых третий символ в фамилии работника суть R, то есть соответствует (LIKE) образцу, который задан как (__R%). Каждый символ подчеркивания (а их два) говорит об одной позиции любого символа, а знак процента (%) задает любую строку без символов или с любым их количеством.
- 21 -
В некоторых вариантах SQL (например, в давно применяющемся в армии США сервере Borland InterBase) присутствует (нестандартная) клауза STARTING (позволяет выбрать строку, начинающуюся с заданного набора символов); некоторые авторы издевательски сопоставляют введение вышеописанной клаузы с 'определенной степенью тугодумия военных', трудно воспринимающих традиционный синтаксис клаузы LIKE выборки по образцу. Операторы сравнения BETWEEN, IN и LIKE можно предварять словом NOT (HE) и соединять с AND и OR для формирования сложных клауз WHERE, предназначенных для выбора нужных строк. Контрольные вопросы 1. Опишите формат SQL-предписания выбора конкретных колонок таблицы. 2. Каким образом SQL позволяет осуществить выбор строк таблицы, удовлетворяющим заданным условиям? 3. С помощью каких приемов осуществляются альтернативные условия поиска в таблице? 4. Каковы символы сравнения по образцу в клаузе LIKE языка SQL? 1.6.Упорядочение строк по запросу Во всех предыдущих примерах строки выводились на экран в порядке, заданном существующей таблицей. Возможно управлять порядком вывода строк на экран путем ввода клаузы ORDER BY (ПО) в конец команды SELECT. Например, если желательно вывести список работников отдела 30, упорядоченный по окладам, следует воспользоваться следующим запросом: SELECT SAL,JOB,ENAME FROM EMP WHERE DEPTNO = 30 ORDER BY SAL; --- пример клаузы ORDER BY SAL 950.00 1,250.00 1,250.00 1,500.00 1,600.00 2,850.0
JOB CLERK SALESMAN SALESMAN SALESMAN SALESMAN MANAGER
ENAME JAMES WARD MARTIN TURNER ALLEN BLAKE
Клауза ORDER BY ведет сортировку строк по увеличивающемуся (меньший оклад сначала) порядку. Но упорядочение не ограничивается
- 22 -
только одной последовательностью в одной колонке. Например, несложно перечислить всех работников по порядку работы и внутри него (порядка работы) по окладу: SELECT JOB,SAL,ENAME FROM EMP ORDER BY JOB, SAL DESC; --- в порядке уменьшения SAL JOB ANALYST ANALYST CLERC CLERC CLERC CLERC MANAGER MANAGER PRESIDENT SALESMAN SALESMAN SALESMAN SALESMAN
SAL 3,000.00 3,000.00 1,300.00 1,100.00 960.00 800.00 2,850.00 2,450.00 5,000.00 1,600.00 1,500.00 1,250.00 1,250.00
ENAME SCOTT FORD MILLER ADAMS JAMES SMITH BLAKE CLARK KING ALLEN TURNER WARD MARTIN
Данные в колонке JOB упорядочены в алфавитном порядке увеличения (это порядок по умолчанию для колонки CHAR) и работники в каждой группе упорядочены по окладам в порядке уменьшения (SAL DESC). Контрольные вопросы 1. В каких случаях используется упорядочение выводимых строк? 2. Каким образом осуществить различный порядок вывода для нескольких различных колонок таблицы? 3. Влияет ли порядок физического расположения строк и колонок в таблице на результат упорядочения их по запросу? 1.7.Предохранение от выбора строк-дубликатов Предполагается, что стоит задача получения списка различных должностей в таблице EMP: SELECT JOB FROM EMP; JOB
- 23 -
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
- 24 -
До сих пор все примеры относились к работе с одной таблицей (ЕМР или DEPT). Запрос типа JOIN (соединение) позволяет выбирать данные из двух или более таблиц и объединять выбранные данные в одной общей таблице. Предположим, что необходимо узнать, где работает работник по фамилии ALLEN. Просматривая две таблицы в БД, можно видеть, что таблица ЕМР не содержит колонку LOC (местоположение), а эта колонка находится в таблице DEPT. Однако обе таблицы имеют колонку DEPTNO - номер отдела. Именно эти номера, содержащиеся в обеих таблицах, позволят соотнести строки из таблицы ЕМР со строками таблицы DEPT. Запрашивая таблицу ЕМР, можно найти номер отдела, где работает ALLEN: SELECT ENAME,DEPTNO FROM ЕМР WHERE ENAME = 'ALLEN'; ENAME ALLEN
DEPTNO 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
- 25 -
ALLEN
CHICAGO
Выражения EMP.DEPTNO и DEPT.DEPTNO позволяют обратиться к заданному столбцу (имя правее точки) нужной таблицы (левее точки). Условия соединения в клаузе WHERE определяет взаимосвязь между таблицами ЕМР и DEPT. В вышеприведенном примере, например, если DEPTNO в строке таблицы ЕМР совпадает с DEPTNO в строке таблицы DEPT (EMP.DEPTNO=DEPT.DEPTNO); в этом случае говорят, что вышеуказанные таблицы связаны по столбцу DEPTNO (на нижерасположенном рисунке показано стрелкой, подобные обозначения часто используют при логическом проектировании БД): Таблица EMP EMPNO 7499
ENAME ALLEN
JOB SALESMAN
DNAME SALES
LOC CHICAGO
DEPTNO 30
Таблица DEPT DEPTNO 30
Соединение данных Вдобавок к условиям соединения, клауза 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 ACCOUNTIG
ENAME KING
JOB PRESIDENT
(*)
SAL 5,000.00
- 26 -
ACCOUNTIG ACCOUNTIG RESEARCH RESEARCH RESEARCH RESEARCH RESEARCH SALES SALES SALES SALES SALES
CLARK MILLER SCOTT FORD JONES ADAMS SMITH BLAKE ALLEN TURNER WARD MARTIN
MANAGER CLERC ANALYST ANALYST MANAGER CLERC CLERC MANAGER SALESMAN SALESMAN SALESMAN CLERC
2,460.00 1,300.00 3,000.00 3,000.00 2,976.00 1,100.00 800.00 2,850.00 1,600.00 1,500.00 1,250.00 950.00
Даже этот простой пример дает понятие о мощности языка SQL. При программировании с помощью процедурных языков процедура соединения всего двух таблиц требует составления и отладки достаточно сложной программы (содержащей минимум один вложенный в другой цикл по записям таблиц), которую к тому же непросто сделать эффективной в работе. Требуемая программа становится значительно более сложной и громоздкой при увеличении количества соединяемых таблиц, время выполнения ее возрастает экспоненциально. В очередной раз подчеркнем, что при использовании SQL пользователь сообщает, ЧТО он хочет получить, а не КАК это сделать. Иерархические и сетевые системы управления базами данных хранят некоторую информацию типа значений и другого типа - указателей. В сетевых системах, например, информация о том, что работник SMITH занимает должность CLERK, хранится как значение в некоем поле. Информация, что SMITH работает в отделе 20, будет храниться как указатель из записи SMITH на запись отдела 20. Только информация, хранимая в виде указателей, может быть использована для сопоставления одной записи другой в сетевой или иерархической базе данных. Решение, хранить ли информацию в виде указателей или значений, должно быть сделано при определении базы данных. Таким образом, сетевая или иерархическая система имеет соотношения, основанные на указателях, и предопределена как статическая; изменение связей потребует перестройки всего файла. В противоположность этому реляционные БД хранят все данные однотипным способом - как значения, хранимые в полях. Можно использовать любое значение для ассоциирования или соединения одной таблицы с другой и легко определить соотношения между значениями, когда вводится запрос, а не когда создаются сами таблицы. Таким образом, соотношения в реляционной базе данных являются осмаксинованными на значениях и динамическими, что обеспечивает мальную гибкость, представляемую пользователю в ответ на самые неожиданные запросы.
- 27 -
Контрольные вопросы 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 ALLEN WARD MARTIN TURNER
SAL 1,600.0 1,250.0 1,260.00 1,500.0
COMM 300.00 500.00 1,400.00 0.00
SAL+COMM 1,900.00 1,750.00 2,660.00 1,500.00
Отметим, что арифметическое выражение (SAL+COMM) выводится как новая колонка в результирующей таблице. Хотя такая колонка, как SAL+COMM, не присутствует в базе данных, она материализовалась как результат запроса, при этом можно работать с ней как с реальной колонкой. Примеры дополнительных арифметических операторов перечислены ниже.
- 28 -
Функции символьных строк Арифметические функции позволяют манипулировать численными данными; точно также функции символьных строк, подобные нижеописанным, упрощают манипулирование символьными данными. Например, можно использовать функцию SOUNDEX для поиска одинаково звучащих имен, пишущихся по-разному. Например, найдем всех работников, имена которых созвучно SCHMIDT: SELECT ENAME FROM EMP WHERE SOUNDEX(ENAME) = SOUNDEX('SCHMIDT'); ENAME SMITH
Поддерживаются следующие арифметические операции, функции и функции символьных строк: Арифметические операторы
Строковые функции
+ * / POWER TRUNC UPPER SOUNDEX
| DECODE LENGTH SUBSTR ROUND ABS LOWER CAST
сложение вычитание умножение деление степень усечение заглавные сопоставление по звучанию
конкатенация транслировать длина строки подстрока округление модуль числа строчные явное преобразование типа данных
Это только часть полного списка арифметических и строковых функций. Смотрите следующие разделы данного учебного пособия для обсуждения групповых функций AVG, SUM,COUNT, MIN, MAX и работы [1...3]. Контрольные вопросы 1. Каким образом осуществляется вывод (несуществующей в таблице) колонки, являющейся арифметическим выражением над колонками данной таблицы? 2. В каких случаях, на Ваш взгляд, оправдано применение функции SOUNDEX?
- 29 -
3. Перечислите базовые арифметические операции и функции, используемые SQL? Какими функциями Вы желали бы дополнить имеющийся набор? 1.10.Вычисление функций групп строк Групповые функции - это еще один показатель мощности SQL. Эти функции позволяют выбирать суммарную информацию из групп строк. Предположим, что необходимо собрать всех работников с одним номером отдела в одну группу и найти максимальный оклад в каждой группе : SELECT DEPTNO,MAX(SAL) FROM EMP GROUP BY DEPTNO; DEPTNO 10 20 30
MAX(SAL) 5,000.00 3,000.00 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 - найти среднее арифметическое значение выбранных колонок в группе. Целью при этом запросе является следующее узнать: сколько работников работает на каждой должности в каждом отделе; например, сколько клерков в исследовательской группе, какова сумма окладов и средний оклад:
- 30 -
SELECT DNAME,JOB,SUM(SAL), --- функция SUM COUNT(*), --- функция COUNT(*) AVG(SAL) --- функция AVG FROM EMP,DEPT WHERE EMP.DEPTNO = DEPT.DEPTNO GROUP BY DNAME, JOB; DNAME ACCOUNTING ACCOUNTING ACCOUNTING RESEARCH RESEARCH RESEARCH SALES SALES SALES
JOB CLERC MANAGER PRESIDENT ANALYST CLERC MANAGER CLERC MANAGER SALESMAN
SUM(SАL) 1,800.00 2,450.00 5,000.00 6,000,00 1,900.00 2,975.00 950.00 2,850.00 5,600.00
COUNT(*) 1 1 1 2 2 1 1 1 4
(**)
АVG(SAL) 1,300.00 2,450.00 5,000.00 3,000.00 950.00 2,975.00 950.00 2,850.00 1,400.00
Рассмотрим работу, которую выполняет программист при создании некоторого вывода, если он применяет традиционную схему программирования. Сначала он получает список работников и сортирует его по номерам отдела и по должности. Далее суммируются число работников и средний оклад вычисляется по номерам отделов и по должности. Наконец, название отдела нужно подставить для номера отдела в выводимой информации. Каждая операция требует циклического чтения записей, сохранения промежуточных результатов, проверки ошибок и т.д. Напротив, непроцедурный подход SQL позволяет создавать такие отчеты, как предыдущий, при помощи указания исполняющей системе только того, ЧТО необходимо сделать: исполняющая система автоматически генерирует процедуру, определяя КАКИМ ОБРАЗОМ извлечь данные таблиц. Клауза HAVING Ранее были определены условия поиска для индивидуальных строк при помощи клаузы WHERE; теперь можно использовать клаузу HAVING для задания условий поиска групп строк. Предположим, что необходимо получить ответ на запрос, подобный предыдущему, но при условии, что каждая группа, выводимая по запросу, должна содержать не менее двух работников: SELECT DNAME,JOB,SUM(SAL),COUNT(*),AVG(SAL) FROM EMP,DEPT WHERE EMP.DEPTNO = DEPT.DEPTNO GROUP BY DNAME,JOB HAVING COUNT(*) >= 2; --- клауза HAVING
(***)
- 31 -
DNAME RESEARCH RESEARCH SALES
JOB ANALYST CLERC SALESMAN
SUM(SAL) 6,000.00 1,900.00 5,600.00
COUNT(*) АVG(SL) 2 3,000.00 2 950.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 JONES BLAKE CLARK
JOB MАNАGER MАNАGER MАNАGER
Исполняющая система обрабатывает подзапрос перед обработкой главного запроса, поскольку его результат нужен для определения результата главного запроса. Вторая команда SELECT в данном примере (а это именно подзапрос) возвращает значение MANAGER, как легко убедиться, если взглянуть на должность работника JONES в таблице EMP. Исполняющая система использует это значение для динамического по-
- 32 -
строения условия поиска WHERE JOB = 'MANAGER', используемого первой командой SELECT для возврата нужных нам строк. Классический пример - перечислить всех работников, получающих больше среднего оклада: SELECT ENAME,SAL FROM EMP WHERE SAL > (SELECT AVG(SAL) FROM EMP); ENAME JONES BLAKE CLARK SCOTT KING FORD
SAL 2,975.00 2,850.00 2,450.00 3,000.00 5,000.00 3,000.00
Подзапросы могут тоже быть составными, как и основные запросы - они могут содержать условия поиска и запросы JOIN. Например, можно использовать их в командах INSERT, UPDATE и DELETE (рассматриваемых в следующих секциях) наряду с командами SELECT. Контрольные вопросы 1. В чем заключается удобство использования подзапросов в SQL-клаузе SELECT? 2. Каков порядок выполнения подзапросов и каким образом его можно изменить? 3. Составьте SQL-предписание для уничтожения строк с информацией о работниках, имеющих оклад не выше 25% от среднего. Каковы ‘подводные камни’, могущие возникнуть при выполнении этой операции? 2.12.Модификация хранимых данных Как видно из вышеизложенного, одна команда SELECT позволяет выбрать набор строк из одной или нескольких таблиц. SQL позволяет добавлять или модифицировать строки достаточно просто при помощи следующих трех команд: • команда UPDATE изменяет значения, хранимые в полях • команда INSERT добавляет строки в таблицу • команда DELETE удаляет строки из таблицы
- 33 -
1.12.1.Команда UPDATE Используя имеющийся пример базы данных, для повышения окладов всех клерков на 100 долларов потребуется обновить или изменить значения некоторых данных (поля SAL) в некоторых строках (тех, в которых значение для JOB = CLERK) в таблице EMP. Команда UPDATE состоит из клаузы UPDATE вместе с клаузой SET и опционной (необязательной) клаузой WHERE: UPDATE EMP SET SAL = SAL + 100 WHERE JOB = 'CLERK’;
Клауза UPDATE определяет таблицу, которую нужно модифицировать (EMP). Клауза SET задает поле, которое нужно модифицировать в некоторое другое значение (SAL=SAL+100). В клаузе WHERE задается условие выбора строк для обновления (условие JOB='CLERK'). Вывод на дисплей подтверждает, что обновление действительно имело место: SELECT ENAME,JOB,SAL FROM EMP WHERE JOB ='CLERK'; ENAME SMITH ADAMS JAMES MILLER
JOB CLERK CLERK CLERK CLERK
SAL 900.00 1,200.00 1,050.00 1,400.00
1.12.2.Команда INSERT Ранее демонстрировалось использование команды INSERT для добавления строк в таблицу, однако это самое примитивное использование инструкции INSERT. Возможно использовать эту команду и для добавления набора строк в таблицу и для копирования строк из одной таблицы в другую. Это делается, используя запрос для определения набора строк, вводимых в таблицу. Предположим, что в ранее описанном примере базы данных имеется третья таблицу по имени PROMOTION. Эта таблица содержит многие колонки такие же как в EMP - ENAME, JOB, SAL, СОММ. Задача введения в эту таблицу данных для всех продавцов, имеющих комиссионные больше 25% от оклада путем копирования информации из таблицы ЕМР решается с помощью следующей SQL-инструкции:
- 34 -
INSERT INTO PROMOTION (ENAME,JOB,SAL,COMM) SELECT ENAME,JOB,SAL,COMM --- подзапрос FROM EMP WHERE COMM > 0.25 * SAL; 2 records created. --- возможное сообщение системы
Команда INSERT в данном примере использует подзапрос вместо списка значений данных. Исполняющая система вводит в таблицу PROMOTION строки и колонки, выбранные из ЕМР в подзапросе. 1.12.3.Команда DELETE Поскольку в отделе 40 нет работников, удалим его из таблицы DEPT при помощи команды DELETE: DELETE FROM DEPT WHERE DEPTNO = 40;
Используем запрос SELECT * , чтобы убедиться, что удаление реально имело место: SELECT * FROM DEPT; DEPTNO 10 20 30
DNAME ACCOUNTIG RESEARCH SALES
LOC NEW YORK DALLAS CHICAGO
Клауза DELETE FROM определяет таблицу, из которой необходимо удалить строку или набор строк (в данном случае таблицу DEPT). Клауза WHERE должна иметь опции (клауза DELETE FROM без нее будет означать, что пользователь желает удалить все строки из таблицы); она задает условия, при соблюдении которых нужно удалять строки. В этом примере использовалась клауза WHERE, чтобы сообщить исполняющей системе следующее ‘УДАЛИТЬ строки таблицы DEPT, у которых значение в колонке DEPTNO равно 40’. Клаузы WHERE во всех командах демонстрируют, как SQL использует одинаковый синтаксис для обработки данных и для запросов. В командах SELECT, UPDATE, INSERT, DELETE функционирование клаузы WHERE идентично: она всегда опционна и используется для задания условий, при которых нужно уничтожать, модифицировать или обновлять данные. Долее будет ясно, как SQL использует одинаковый синтаксис запросов для опреде-
- 35 -
ления данных. Контрольные вопросы 1. Каков формат SQL-предписаний UPDATE, INSERT и DELETE? 2. Каким образом команда INSERT используется для переноса (по заданному условию) данных из одной таблицы в другую? 1.13.Динамические изменения структуры базы данных Поддерживаются команды SQL, необходимые для динамического изменения структуры базы данных. В данном разделе будут приведены необходимые для этого инструкции SQL: • ALTER TABLE ADD - добавления новой колонки в существующую таблицу • ALTER TABLE MODIFY - изменение размера существующей колонки Для примера расширим вышеописанную базу данных так, что в дальнейшем сможем назначить работников для проектов так же, как назначали их для отделов. Это изменение структуры базы данных требует нескольких шагов. Сначала при помощи команды CREATE TABLE создадим таблицу проектов: CREATE TABLE DEPT (PROGNO PNAME BUDGET
NUMBER (3) NOT NULL, CHAR (5), NUMBER(7,2));
Далее используем команду INSERT для помещения некоторых данных в таблицу PROJ: INSERT INTO PROJ VALUES (101, 'ALPHA', 96000) INSERT INTO PROJ VALUES (101, 'BETA', 82000) INSERT INTO PROJ VALUES (101, ‘GAMMA', 96000)
Проверим корректность создания таблицы PROJ: SELECT * FROM PROJ; PROJNO 101 102
PNAME ALPHA BETA
BUDJET 96,000.00 82,000.00
- 36 -
103
GAMMA
15,000.00
И в третьих, добавим колонку номеров проектов в таблицу ЕМР, так что две таблицы разделят общую колонку. Используем команду ALTER TABLE для добавления новой колонки в существующую таблицу : ALTER TABLE ЕМР ADD (PROJNO NUMBER(3));
В данной команде названа таблица, которую нужно изменить (в данном случае ЕМР), описана функция добавления (ADD), колонка, которую нужно добавить в нее (PROJNO), новый тип данных колонки и максимальная длина новой колонки - NUMBER(3). Просмотрим таблицу ЕМР и заметим, что добавлено в каждую строку новое поле PROJNO с пустым начальным значением: SELECT * FROM ЕМР; EMPNO 7369 7499 7521 7566 7654 7698 7782 7788 7839 7844 7876 7900 7902 7934
ENAME SMITH ALLEN WARD JONES MARTIN BLAKE CLARK SCOTT KING TURNER ADAMS JAMES FORD MILLER
JOB CLERK SALESMAN SALESMAN MANAGER SALESMAN MANAGER MANAGER ANALYST PRESIDENT SALESMAN CLERK CLERK ANALYST CLERK
MGR 7902 7698 7698 7839 7698 7839 7839 7566 7698 7788 7698 7566 7782
HIREDATE 17-DEC-80 20-FEB-81 22-FEB-81 02-APR-81 28-SEP-81 01-MAY-81 09-JUN-81 09-NOV-81 17-NOV-81 08-SEP-81 23-SEP-81 03-DEC-81 03-DEC-81 23-JAN-82
SAL 8,00.00 1,600.00 1,250.00 2,975.00 1,250.00 2,850.00 2,450.00 3,000.00 5,000.00 1,500.00 1,100.00 950.00 3,000.00 1,300.00
COMM 300.00 500.00 1,400.00
DEPTNO 20 30 30 20 30 30 10 20 10 30 20 30 20 10
PROJNO
После введения новой колонки в таблицу ЕМР применим команду UPDATE для соотнесения работников с проектами. Соотнесем всех работников отдела 20 и всех продавцов проекту 101: UPDATE ЕМР SET PROJNO = 101 WHERE DEPTNO = 20 OR JOB = 'SALESMAN';
Выведем на экран полученную таблицу ЕМР для уверенности во введенных изменениях: SELECT *
- 37 -
FROM ЕМР; EMPNO 7369 7499 7521 7566 7654 7698 7782 7788 7839 7844 7876 7900 7902 7934
ENAME SMITH ALLEN WARD JONES MARTIN BLAKE CLARK SCOTT KING TURNER ADAMS JAMES FORD MILLER
JOB CLERK SALESMAN SALESMAN MANAGER SALESMAN MANAGER MANAGER ANALYST PRESIDENT SALESMAN CLERK CLERK ANALYST CLERK
MGR 7902 7698 7698 7839 7698 7839 7839 7566 7698 7788 7698 7566 7782
HIREDATE 17-DEC-80 20-FEB-81 22-FEB-81 02-APR-81 28-SEP-81 01-MAY-81 09-JUN-81 09-NOV-81 17-NOV-81 08-SEP-81 23-SEP-81 03-DEC-81 03-DEC-81 23-JAN-82
SAL 8,00.00 1,600.00 1,250.00 2,975.00 1,250.00 2,850.00 2,450.00 3,000.00 5,000.00 1,500.00 1,100.00 950.00 3,000.00 1,300.00
COMM 300.00 500.00 1,400.00
DEPTNO 20 30 30 20 30 30 10 20 10 30 20 30 20 10
PROJNO 101 101 101 101 101
101 101 101
Теперь поместим всех, кто не отнесен ни к какому проекту (то есть WHERE PROJNO IS NULL), в проект 102: UPDATE EMP SET PROJNO = 102 WHERE PROJNO IS NULL;
Другой запрос в таблицу EMP показывает, что все работники теперь имеют значения в поле PROJNO: SELECT * FROM EMP; EMPNO 7369 7499 7521 7566 7654 7698 7782 7788 7839 7844 7876 7900 7902 7934
ENAME SMITH ALLEN WARD JONES MARTIN BLAKE CLARK SCOTT KING TURNER ADAMS JAMES FORD MILLER
JOB CLERK SALESMAN SALESMAN MANAGER SALESMAN MANAGER MANAGER ANALYST PRESIDENT SALESMAN CLERK CLERK ANALYST CLERK
MGR 7902 7698 7698 7839 7698 7839 7839 7566 7698 7788 7698 7566 7782
HIREDATE 17-DEC-80 20-FEB-81 22-FEB-81 02-APR-81 28-SEP-81 01-MAY-81 09-JUN-81 09-NOV-81 17-NOV-81 08-SEP-81 23-SEP-81 03-DEC-81 03-DEC-81 23-JAN-82
SAL 8,00.00 1,600.00 1,250.00 2,975.00 1,250.00 2,850.00 2,450.00 3,000.00 5,000.00 1,500.00 1,100.00 950.00 3,000.00 1,300.00
COMM 300.00 500.00 1,400.00
DEPTNO 20 30 30 20 30 30 10 20 10 30 20 30 20 10
PROJNO 101 101 101 101 101 102 102 102 102 101 101 102 101 102
Обновление строк работников с номерами проектов завершает модификацию базы данных и позволяет соотносить работников с проектами так же как с отделами. Присоединение таблицы EMP к таблице PROJ:
- 38 -
SELECT ENAME,JOB,DEPTNO,PNAME FROM EMP,PROJ WHERE EMP.PROJNO = PROJ.PROJNO; ENAME SMITH ALLEN WARD JONES MARTIN SCOTT TURNER ADAMS FORD BLAKE CLARK KING JAMES MILLER
JOB CLERK SALESMAN SALESMAN MANAGER SALESMAN ANALYST SALESMAN CLERK ANALYST MANAGER MANAGER PRESIDENT CLERK CLERK
DEPTNO 20 30 30 20 30 20 30 20 20 20 10 10 30 10
PNAME ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA BETA BETA BETA BETA BETA
При помощи этой серии примеров была продемонстрирована легкость, с которой можно динамически расширять и реструктуризировать базу данных. Сначала была создана новая таблица. Затем в нее добавили новую колонку. После этого поместили данные в эту колонку. И, наконец, слили новую и старую таблицу. Все четыре операции были выполнены с помощью простых команд SQL без вмешательства системы для загрузки и перезагрузки данных или явной реорганизации какой-то части базы данных. Команда ALTER TABLE В дополнение к возможности добавлять новые колонки существующие таблицы, можно изменить размер существующих колонок. Например, что было введено значение 15000 для бюджета в проекте 103. Предположим, что произошла ошибка и правильное значение в действительности должно быть равно 105000. Необходимо обновить строку проект 103 с правильным значением бюджета: UPDATE PROJ SET BUDGET = 105000 WHERE PROJNO = 103; ERROR: для колонки задано значение больше допустимого
- 39 -
Получено сообщение об ошибке, поскольку сумма нового бюджета, которую попытались ввести, была слишком велика, чтобы поместиться в колонку BUDGET, определенную в команде CREATE TABLE как NUMBER(7,2). Это определение значит, что допускаются числа не больше чем 99,999.99 (7 цифр, из которых две справа от десятичной точки). Проблему можно решить, используя команду ALTER TABLE для увеличения колонки: ALTER TABLE PROJ MODIFY BUDGET NUMBER(8,2);
Также как в команде ALTER TABLE ADD, указывается таблица PROG, которую надо изменить. В данном примере необходимо модифицировать определение колонки BUDGET (определить ее размер как NUMBER(8,2) вместо текущей. Теперь можно попытаться обновить таблицу снова: UPDATE PROJ SET BUDGET = 105000 WHERE PROJNO = 103;
Используем запрос SELECT для уверенности, что обновление действительно имело место: SELECT * FROM PROJ; PROJNO 101 102 103
PNAME ALPHA BETA GAMMA
BUDJET 96,000.00 82,000.00 105,000.00
Контрольные вопросы 1. В каких случаях необходимо динамически изменять структуру таблицы? 2. Каков формат SQL-предписаний, осуществляющих динамическое изменение структуры данных? 3. Каким образом пользователь может отслеживать возможные ошибки, возникающие вследствие непродуманного изменения структуры таблиц? 4. Насколько, по Вашему мнению, динамическое изменение структуры таблиц с помощью SQL эффективнее традиционного подхода (создание новой таблицы c заданной структурой → копирования в нее содержимого имеющейся таблицы → добавление необходимых данных → уничтожение ‘старой’ таблицы)?
- 40 -
1.14.Альтернативные виды данных Поддерживающие язык SQL системы позволяют создавать и обрабатывать альтернативный вид данных - вид (VIEW, иное русскоязычное название - представление). Виды можно представить виртуальными таблицами; они подобны окнам, через которые можно просматривать данные, хранимые в реальных таблицах. Виды (именуемые также виртуальными таблицами, просматриваемыми таблицами) не содержат данных самих по себе, а являются запросами, выполняющимися всякий раз, когда в операторе встречается ссылка на данный вид (таким образом достигается актуальность вида). Также любое изменение данных в таблицах сразу же вызывает соответственное изменение связанного с данными таблицами вида; образно говоря, изменения в 'окружающем пространстве' (таблицах) тут же проявляются в ’окне’ (виде). Виды (представления) используются аналогично любой таблицы - к видам можно обращаться с запросами, обновлять, вставлять или удалять данные или соединять его с другими таблицами или видами. Имена столбцов вида могут не совпадать с именами соответственных столбцов породивших вид таблицах. Обычно изменения в виде сразу же сказывается на содержании породивших его таблиц (в этом случае говорят, что ‘вид обновляем’), однако существуют случаи, когда вид существует ‘только для чтения’. Вопрос определения критериев ‘обновляемости’ видов до сих пор дискуссируется в теории баз данных (некоторые практические примеры можно найти в [1]). Виды служат трем основным целям • упрощают доступ к данным • обеспечивают независимость данных • обеспечивают защиту данных Рассмотрим, как создаются виды и как их можно использовать для упрощения доступа к данным. Создадим вид таблицы ЕМР, который будет поднабором всей таблицы и будет включать только номера, фамилии и работу работников, занятых в отделе 10: CREATE VIEW EMPN0 AS SELECT EMPNO,ENAME,JOB FROM ЕМР WHERE DEPTNO = 10;
Поскольку результат запроса - таблица, то запрос используется для оп-
- 41 -
ределения виртуальной таблицы или вида. В команде CREATE VIEW называется вид, а затем описывается в форме оператора запроса SQL, что вид должен содержать. С некоторыми ограничениями можно запрашивать и модифицировать виды так же, как если бы они были реальными таблицами. Просмотрим созданный вид: SELECT * FROM EMPNO; EMPNO 7782 7839 7934
ENAME CLARK KING MILLER
JOB MANAGER PRESIDENT CLERK
Для некоторых пользователей проще работать с одной таблицей, чем с несколькими. Поддерживающие SQL системы позволяют создавать единственный вид из двух или более таблиц. Таким образом, возможно определить вид как выборку из нескольких таблиц, вместо которых можно запрашивать индивидуально сделанное соединение (это и есть вид). Несложно создать единственный вид таблицы по имени PERSONNEL с колонками ENAME, JOB, PNAME из таблиц ЕМР и PROJ и затем проанализировать его содержимое. Создание соединенного вида: CREATE VIEW PERSONNEL AS SELECT ENAME,JOB,PNAME FROM EMP,PROJ WHERE EMP.PROJNO = PROJ.PROJNO;
Просмотр созданного вида: SELECT * FROM PERSONNEL; PROJNO SMITH ALLEN WARD JONES MARTIN SCOTT TURNER ADAMS FORD BLAKE
JOB CLERK SALESMAN SALESMAN MANAGER SALESMAN ANALYST SALESMAN CLERK ANALYST MANAGER
PNAME ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA BETA
- 42 -
CLARK KING JAMES MILLER
MANAGER PRESIDENT CLERK CLERC
BETA BETA BETA BETA
После создания вида пользователь никак не сможет узнать, что данные, которые он просматривает, хранятся в двух таблицах. Более того, можно считать, что данные хранятся в одной таблице (данном виде). Таким образом можно использовать виды для упрощения доступа к данным, уменьшения длины строк и сокращения количества ошибок. Используя вид PERSONNEL, перечислим имена менеджеров и проекты, над которыми они работают: SELECT ENAME,PNAME FROM PERSONNEL WHERE JOB = 'MANAGER'; ENAME JONES BLAKE CLARK
PNAME ALPHA BETA BETA
Отметим, насколько прост этот запрос вида PERSONNEL по сравнению с запросом типа JOIN, требуемым для выполнения аналогичных действий генерации этого списка из двух таблиц ЕМР и PROJ. Контрольные вопросы 1. Что такое представления (виды) и чем они функционально отличаются от таблиц? 2. Каким целям служат представления? 3. Каким образом достигается актуальность содержимого представления? 4. Должно ли представление иметь одинаковое имя с таблицей, от которой порождено? 5. Возможно ли создание представления, включающего информацию из нескольких таблиц одновременно? 1.15.Независимость данных Виды освобождают пользователя от необходимости знать, в каких таблицах находятся данные, c которыми он работает. Это разница в том, какие данные пользователь видит и как они хранятся, носит название независимость данных; эта разница упрощает доступ к данным в БД. Но можно ис-
- 43 -
пользовать виды и для хранения пользовательских запросов, программ и так далее, предохраняя их от устаревания при изменениях базы данных. Текущая структура БД позволяет связать несколько работников с проектом, однако каждый должен работать только по одному проекту - это известное соотношение 'многие к одному'. Предположим, что процедуры по персоналу изменились и сейчас есть необходимость связать работников с несколькими проектам. Чтобы это выполнить, необходимо пересмотреть структуру базы данных, преследуя две цели. Первая цель - предохранить старые виды БД, чтобы можно было продолжать работы со всеми прикладными системами, отчетами и программами, зависящими от исходной структуры базы данных. Вторая цель заключается в том, чтобы иметь возможность использовать новые данные (дополнительные проекты) для построения новых прикладных систем. Ниже приведены этапы достижения поставленной цели. Сначала создадим новую таблицу, соотносящую работников с проектами и содержащую информацию об участии конкретных работников в конкретном проекте (например, введем новый столбец - часы работы WORKHPS. Новая структура базы данных будет поддерживать соотношения типа 'многие-к-многим'): CREATE TABLE PE (EMPNO PROJNO WORKHPS
NUMBER (4), NUMBER (3), NUMBER (4));
Далее присоединим работников к проектам путем введения строк в таблицу РЕ. Отметим, что работник под номером 7369 имеет две строки в этой таблице: одна для проекта 101 и другая - для 102. Присоединение работников к проектам выполняется многократным использованием INSERT: INSERT INTO PE VALUES (7369, 101, 0); INSERT INTO PE VALUES (7369, 102, 0); INSERT INTO PE VALUES (7399, 101, 0); INSERT INTO PE VALUES (7521, 101, 0); INSERT INTO PE VALUES (7366, 101, 0); INSERT INTO PE VALUES (7554, 101, 0); INSERT INTO PE VALUES (7698, 102, 0); INSERT INTO PE VALUES (7782, 102, 0); INSERT INTO PE VALUES (7788, 101, 0); INSERT INTO PE VALUES (7839, 102, 0); INSERT INTO PE VALUES (7844, 101, 0); INSERT INTO PE VALUES (7876, 101, 0); INSERT INTO PE VALUES (7900, 102, 0); INSERT INTO PE VALUES (7902, 101, 0); INSERT INTO PE VALUES (7934, 102, 0);
- 44 -
В будущем, если работник будет присоединен ко второму или третьему проекту, достаточно ввести дополнительную строку для этого работника в таблицу РЕ. Поскольку теперь используется таблица РЕ для соотношения работников с проектами, больше не нужна информация, хранимая в колонке PROJNO таблицы ЕМР. Можно удалить эти данные путем установки значений этой колонки в пустые: UPDATE EMP SET PROJNO = NULL;
Вспомним, что отсутствие клаузы WHERE приказывает обновить все строки в таблице. Поскольку все PROJNO установлены в NULL, больше невозможно использовать вид PERSONNEL, который использует колонку PROJNO для связи таблиц ЕМР и PROJ. Для генерации этой информации снова нужно соединить таблицу ЕМР с новой таблицей РЕ и соединить таблицу РЕ с нашей таблицей PROJ. Но возможно спрятать это изменение от пользователей, использующих вид PERSONNEL, просто изменив определение вида. Первый шаг в изменении вида PERSONNEL - уничтожить старый вид: DROP VIEW PERSONNEL;
Теперь создадим новый вид PERSONNEL, объединяющий таблицу ЕМР и таблицу PROJ через таблицу РЕ : CREATE VIEW PERSONNEL AS SELECT ENAME,JOB,PNAME FROM EMP,PROJ,PE WHERE EMP.EMPNO = PE.EMPNO AND PE.PROJNO = PROJ.PROJNO;
Теперь программы, использующие старый вид PERSONNEL, могут продолжать работу без модификации и пользователи могут работать со старыми данными в общем случае, не боясь изменений в базе данных. Запрашивая новый вид PERSONNEL, увидим такую же информацию, как для старого вида PERSONNEL плюс второй проект для работника SMITH: SELECT * FROM PERSONNEL ORDER BY ENAME; ENAME
JOB
PNAME
- 45 -
ADAMS ALLEN BLAKE CLARK FORD JAMES JONES KING MARTIN MILLER SCOTT SMITH SMITH TURNER WARD
CLERK SALESMAN MANAGER MANAGER ANALYST CLERK MANAGER PRESIDENT SALESMAN CLERK ANALYST CLERK CLERK SALESMAN SALESMAN
ALPHA ALPHA ALPHA ALPHA ALPHA BETA ALPHA BETA ALPHA BETA ALPHA ALPHA BETA ALPHA ALPHA
SMITH работает по двум проектам - ALPHA и BETA
Только что был продемонстрирован пример, как можно легко изменить структуру базы данных без изменений пользовательских программ, хранимых запросов и др. Это возможно именно потому, что SQL является непроцедурным языком и позволяет иметь разные виды (представления) одних и тех же данных. Контрольные вопросы 1. В чем заключается независимость данных? 2. Допустимо ли использовать представления для хранения не только традиционных данных, но и текстов пользовательских запросов, программ и др.? 3. Каким образом с помощью представлений можно обеспечить функционирование старых программ без их модификации? 1.16.Разделение данных и защита Поддерживающие язык SQL системы дают возможность многочисленным пользователям иметь доступ к одной базе данных. Это позволяет разделять (по желанию) свои данные с другими пользователями. В данном разделе обсуждается, как использовать SQL для: • ГАРАНТИИ привилегий в таблицах и видах для других пользователей • ОТМЕНЯТЬ привилегии, которые ранее были гарантированы другим пользователям Данный пользователь является полновластным владельцем любой созданной им таблицы (обладает всеми привилегиями доступа к ней - на чтение,
- 46 -
изменение, уничтожение данных). Для регулирования доступа для других пользователей служит инструкция GRANT. Команда GRANT состоит из трех базовых клауз:
к
данным
GRANT привилегия ON таблица или вид ТО пользователь или группа пользователей;
Предположим, что текущий пользователь является создателем таблицы ЕМР и желает дать пользователю по имени ADAMS право на запросы к ней. Для этого следует задать команду: GRANT SELECT ON EMP TO ADAMS;
Возможно гарантировать любую комбинацию привилегий функционирования в таблицах или видах, включая: Привилегии для таблиц SELECT выбрать INSERT ввести UPDATE обновить DELETE удалить ALTER изменить INDEX индексировать CLUSTER кластер
Привилегии для видов SELECT выбрать INSERT ввести UPDATE обновить DELETE удалить
В предыдущем примере пользователю ADAMS гарантированы привилегии на выборку из всей таблицы EMP. Но что будет, если необходимо обеспечить всем пользователям доступ ко всей таблице, за исключением колонок SAL и СОММ? Вопрос может быть решен путем гарантирования привилегий к видам, а не таблицам. Можно ограничить доступ к заданным строкам и колонкам таблицы. Сначала определим вид EMP, который не содержит колонки SAL и СОММ: CREATE VIEW EMPS AS SELECT EMPNO,ENAME,JOB,HIREDATE,DEPTNO FROM EMP;
Теперь легко гарантировать привилегии на доступ к виду EMPS для всех пользователей при помощи ключевого слова PUBLIC:
- 47 -
GRANT SELECT ON EMPS TO PUBLIC; --- PUBLIC значит ‘ДЛЯ ВСЕХ’
Еще одна возможность SQL - он позволяет создавать виды, возвращающие разные результаты разным пользователям ! Создадим вид таблицы EMP, возвращающий данные только о тех пользователях, номера отдела которых совпадают с номером отдела персоны, использующей данный вид: CREATE VIEW MYEMPS AS SELECT * FROM EMP WHERE DEPTNO IN (SELECT DEPTNO FROM EMP WHERE ENAME = USER);
Ключевое слово USER (используемое в конструкции WHERE ENAME=USER) возвращает имя текущего вошедшего в систему пользователя. Если это JONES, работающий в отделе 10, то он имеет доступ к виду MYEMPS, где перечислены только работники отдела 10. Если это BLAKE (из отдела 30), то он увидит только работников отдела 30. Другими словами, вид становится чувствительным к тем, кто его использует. Несложно гарантировать доступ и привилегии обновления к виду MYEMPS для всех трех менеджеров отделов для разрешения им читать и изменять любые данные о работниках только их отделов: GRANT SELECT,UPDATE ON MYEMPS ТО JONES, BLAKE, CLARK;
Таким образом, если работник переведен в другой отдел (то есть значение в поле DEPTNO изменилось), новый менеджер автоматически получает доступ к сведениям по окладу данного работника, а старый менеджер отдела автоматически теряет к нему доступ. Сочетание возможностей VIEW и GRANT, а также ключевого слова USER, дает поддерживающим SQL системам способность осуществлять защиту, чувствительную к содержимому БД. Команда REVOKE После предоставления привилегии всегда можно ее отменить при помощи команды REVOKE.
- 48 -
Например, для отмены привилегий ADAMS на введение значений в таблицу DEPT следует задать следующую SQL-инструкцию: REVOKE INSERT ON DEPT FROM ADAMS;
Контрольные вопросы 1. Каким образом подтверждаются и отменяются привилегии пользователей на доступ к конкретной таблице БД? 2. Какими привилегиями обладает пользователь по отношению к созданной по его требованию таблице? 3. Каким образом осуществляется разделение привилегий на доступ к отдельным столбцам таблицы? 4. В чем заключается принцип защиты информации, чувствительный к содержимому БД? 1.17.Понятие транзакции Транзакция - логическая единица работы, определяемая пользователем. Важнейшим свойством транзакции является ее атомарность - транзакция должна или завершиться полностью и успешно, или не завершиться совсем. В качестве логической единицы может выступать любое количество операторов SQL (однако целесообразно включать в единичную транзакцию логически связанные запросы). Смысл реализации транзакций - повышение уровня целостности информации в БД в критических ситуациях (например, в случае потери связи с удаленной БД, при сбое питания и др.). Транзакцию (или логическую единицу работы) можно определить как последовательность ряда таких операций, которые преобразуют некоторое непротиворечивое состояние базы данных в другое непротиворечивое состояние (но не гарантируют сохранения непротиворечивости во все промежуточные моменты времени). Транзакция начинается выдачей команды BEGIN TRANSACTION (т.е. начать вести журнал транзакции, в который записываются все необходимые изменения в БД). Далее следуют команды изменения БД (‘тело’ транзакции). Транзакция может завершиться успешно (для чего выдается команда COMMIT) или может быть проведен 'откат’ данной транзакции (по команде ROLLBACK) к исходному (до момента начала транзакции) состоянию БД. Команды COMMIT или ROLLBACK могут являться условными; по умолчанию COMMIT выполняется в случае успешного выполнения тела транзакции (что определяется согласно записям в журнале транзакций), в противном случае выполняется ROLLBACK. Естественно, пользователь
- 49 -
(обычно привилегированный) имеет возможность ‘откатить’ все зарегистрированные в журнале транзакции. Контрольные вопросы 1. Дать определение транзакции. Для применяются транзакции? 2. В чем заключается основное свойство транзакции? 3. Что такое журнал транзакций и какие функциональные возможности осуществляются с его помощью? 1.18.Понятие триггера Триггер (понятие было введено в Oracle) является разновидностью хранимой (т.е. сохраняемой отдельно, а не входящей в код выполняемой программы) процедуры, срабатывающей автоматически при наступлении определенного события и возвращающей логическое значение. Различают триггеры уровня блоков (активируются при выполнении запросов) и триггеры уровня записей (активируются в моменты изменений в полях БД). Триггеры также разделяются на пред-триггеры (активируются перед выполнением некоего действия) и пост-триггеры (активируются после выполнения действия) Тело триггера может содержать любое число SQL-операторов, возвращающих значение ИСТИНА при выполнении заложенного в теле триггера условия или ЛОЖЬ в противоположном случае. Простейший случай использования триггера - обеспечение ссылочной целостности БД. Например, в случае попытки удаления записи в MASTERтаблице триггер должен проверить наличие соответствующих ссылок в DETAIL-таблице (вернув значение ИСТИНА при их наличии и ЛОЖЬ в случае отсутствия); программа пользователя при получении значении ИСТИНА от данного триггера обязана отменить удаление записи. Триггеры являются интуитивно понятным и мощнейшим средством обеспечения корректности функционирования СУРБД. Контрольные вопросы 1. Что такое триггер (в понятиях SQL)? 2. Триггеры каких уровней и типов существуют? 3. Привести пример использования триггера при работе с БД. 2. ПРАКТИЧЕСКОЕ ИСПОЛЬЗОВАНИЕ SQL НА ПЭВМ 2.1.Создание приложений класса баз данных в Delphi / С++Builder
- 50 -
Создание приложений класса баз данных в Delphi / С++Builder производится быстро и легко, в то же время достигается большая гибкость в применении. Освоение фирмой Borland операционной системы Linux (RADсистема Kylix, см. http://www.borland.ru/kylix/index.html) еще более повышает ценность накопленных при работе с Delphi / С++Builder навыков программирования. В основном применяются следующие компоненты Delphi / С++Builder (находятся на страницах DataAceess и DataControls стандартной линейки компонентов): • компонент ТТаblе для доступа к БД без использования SQL или ориентированный на SQL компонент TQuery доступа к БД; эти компоненты осуществляют физический доступ к БД на диске; • компонент TDataSource для связи ТTаblе/TQuery с (видимыми) компонентами представления информации БД; • компонент TDBGrid для визуального представления информации в виде стандартной таблицы (строки коей соответствуют записям, а столбцы полям БД). Часто применяют компонент TFieldList, обеспечивающий задание и визуализацию пользовательских заголовков полей в таблицах, компоненты TDBEdit, TDBImage для доступа/редактирования полей таблиц, компонент TDBNavigator для удобного перемещения по записям БД и др. Для реализации систем класса 'клиент/сервер' обычно дополнительно применяются компоненты TStoredProc и TBatchMove Таким образом, схема простейшей машины БД в Delphi / С++Builder может быть представлена на рис.2.1. Для создания простейшей системы управления БД разработчик должен поместить на форму компоненты TTable/TQuery, TDataSource, TDBNavigator / TDBGrid / TDBEdit / TDBImage и настроить их соответствующим образом с помощью Object Inspector'a. Экран приложения на Delphi / C++Builder TTable или TQuery IndexNames IndexFieldNames
TDBGrid
TFieldList TDataSource
Оперативная память
- 51 -
Дисковая память Таблица индексов Физическая таблица на диске (файл) Рис.2.1. Простейшая машина баз данных (схема)
Настройка компонент TDBNavigator/TDBGrid и TDBEdit / TDBMemo / TDBImage заключается в установке свойства DataSource на имя реального компонента TDataSource (а для компонентов TDBEdit / TDBMemo / TDBImage - свойства DataFleld на имя отображаемого поля). Настройка компонента TDataSource заключается в установке свойства DataSet на имя реального компонента ТТаblе или TQuery Настройка компонента ТТаblе заключается в установке свойства DatabaseName на имя алиаса нужной таблицы, свойств IndexFieldName или IndexName - на имя ключа, свойства TableName - на имя содержащего таблицу файла, свойства ТаblеТуре - на тип файла БД (dBase, Paradox etc). Настройка компонента TQuery заключается в установке свойства DatabaseName как указано выше, (необязательных) установках свойств SQL (задать строку SQL-запроса) и Params (задать фактические значения используемых в SQL-запросе параметров). Часто свойства SQL и Params не устанавливаются в Object Inspector'e, a прямо присваиваются в RunTime (как показано ниже). Установка свойства Active в TRUE (даже в DesignTime) компонентов ТТаblе и TQuery инициирует немедленное открытие нужной таблицы (весьма рекомендуется при отладке). Практические советы по настройке компонентов можно найти в [6,7]. Существенно, что о каждой (физической) таблицей могут быть связаны несколько компонентов TTable/TQuery и др., что бывает необходимо для открытия таблицы в разных режимах. Сложности может вызвать настройка алиасов (псевдонимов) полных путей к файлам БД в компонентах ТTаblе/TQuery. Пользователь должен задать имя алиаса для каждой физической таблицы или для всех используемых в данном приложении таблиц (или разбить файлы на группы по месту их расположения на диске). Компонент TQuery использует SQL-выражения для доступа к БД, причем возможны три пути определения SQL-предложения: • статическое SQL-выражение (задается во время DesignTime в свойстве SQL и в простейшем случае не изменяется во время выполнения скомпилированного приложения); • SQL-выражение с параметрами (текст SQL-запроса может содержать на-
- 52 -
чинающиеся с двоеточия формальные параметры, изменяемые во время выполнения скомпилированного приложения); • динамическое задание SQL-запроса; в этом случае текст (строка) SQLзапроса генерируется в RunTime и передается компоненту TQuery для исполнения. Простейшая схема использования возможностей компонента TQuery, обеспечивающая функционирование SQL-запросов к БД приведен ниже (Cтекст дан применительно к системе C++Builder, предполагается, что текст SQL-запроса вводится пользователем в компонент Edit1): void __fastcall TForm1::RunSQL(TObject *Sender) { // функция вызывается при нажатии // на кнопку ‘RunSQL’ (‘Выполнить SQL’) Query1->Close(); // закрыть БД Query1->SQL->Clear(); // очистить буфер SQL-предписаний Query1->SQL->Add(Edit1->Text); // копировать в буфер из Edit1 Query1->Open(); // заново открыть БД (c выполнением SQL) } // конец функции RunSQL
Приближенный к практике Раsса1-текст (для Delphi) в этом случае будет следующим (полагаем, что имя TQuery-компонента суть Query_l, a строки SQL_string_l, SQL_string__2 и др. содержат ранее сгенерированные тексты частей SQL-запроса - например, отдельно SELECT-часть, WHERE-часть и др.): ..... try { включить режим отслеживание исключительных ситуаций } Screen.Cursor:=crSQLWait;{ форма курсора - песочные часы } Query_1.Close; Query_1.SQL.Clear; { очистить текст SQL-запроса } Qnery_1.SQL.Add(SQL_string_1); { 1-я часть SQL-запроса } Query_1.SQL.Add(SQL_string_2); { 2-я часть SQL-запроса } { и так далее - текст запроса может быть достаточно длинным... } Query_1.Prepare; { ...часто повышает эффективность } Query_1.Open; { выполнение SELECT - запроса} Screen.Cursor:=crDefault; { форма курсора - по умолчанию } except { ...какая-то ошибка при выполнении OPEN } on E:EDatabaseError do begin if E.Message=LoadStr(SHandleError) then { ...это не SELECT !} begin Query1.ExecSQL; { попытка выполнения не SELECT - запроса } Screen.Cursor:=crDefault; { форма курсора - по умолчанию } end else begin { ошибка выполнение не SELECT - запроса }
- 53 -
Sсreen.Cursor:=crDefault; { форма курсора - по умолчанию } { raise; возбудить исключительное состояние } MessageDlg('Ошибка выполнения UPDATE,DELETE или ' + ‘INSERT', mtError, [mbOk], 0); end; end else begin { непонятная ошибка... } Screen.Cursor:=crDefault; { форма курсора - по умолчанию } { raise; возбудить исключительное состояние } MessageDlg('Нераспознанная ошибка SQL-запроса к БД', mtError,[mbOk],0); end; end; { конец блока TRY } .....
Именно при выполнении метода Open происходит (физическое) соединение с БД, выполнение SQL-запроса и дальнейшая визуализация полученных данных. При наличии в SQL-предложении клауз INSERT, UPDATE, DELETE следует вместо метода Open использовать метод ExecSQL (метод Open используется только тогда, когда запрос предполагает возвращение результата - т.е. используется клауза SELECT). Для успешной работы следует корректно настроить соответствие алиаса физическому пути к файлу БД и параметры соединения с помощью BDE (Borland Database Engine), в основе которого лежит технология IDAPI (Integrated Database API), см. [6,7] и др. Контрольные вопросы 1. Какие компоненты интегрированных сред Delphi / C++Builder применяются при создании приложений класса БД и какие функции они выполняют? 2. В чем разница использования методов Open и ExecSQL и в каких случаях они применяются? 3. С помощью каких программных средств устанавливается соответствие алиаса и пути к файлам БД и параметры соединения? 2.2.Использование тренажера локального SQL Конструирование корректных SQL-предложений на начальном этапе работы с языком SQL может вызвать затруднения, причем отладка SQLзапросов совместно с разрабатываемым Windows-приложением неэффективна из-за больших затрат на компиляцию (интерпретацию) базового приложения. В связи с огромными возможностями языка SQL конечный результат за-
- 54 -
проса может быть достигнут различными способами (например, с использование или без использования вложенных запросов); эффективность (время выполнения и требуемый объем оперативной памяти) SQL-запроса при этом может изменяться в значительной степени, поэтому рационально использовать специальные программы-тренажеры (имитаторы выполнения) языка SQL. При таком подходе SQL-запросы сначала конструируются и оптимизируются пользователем с использованием тренажера и только потом переносятся в приложение. Особенно эффективен такой подход для создания сложных хранимых SQL-процедур. 2.2.1.Тренажер SQL-запросов к одной таблице Для освоения (локального) SQL разработан простой тренажер в применении SQL, исполняемый файл которого называется SQL_1. ЕХЕ. Тренажер позволяет исполнять SQL-предложения при работе с локальной БД, название файла БД - ЕМР (по строению совпадает с приведенным выше), имя алиаса - ЕМР. Текст SQL-запроса вводится пользователем и исполняется, результат исполнения визуализируется тут же в таблице, ошибка индицируется. Само SQL-выражение запоминается в дисковом файле с расширением SQL_1.SQL и восстанавливается при перестартовке тренажера. При работе с тренажером имеется возможность пользоваться системой контекстного HELP'a (используется файл LOCALSQL.HLP из поставки Delphi); для вызова системы помощи следует пользоваться клавишей F1 (или Ctrl+Fl) или щелкнуть правой кнопкой 'мыши'. Для перемещения по записям БД служит компонент TDBNavigator, представленный в виде линейки с кнопками в левой нижней части окна; он же используется для удаления записей, их изменения/добавления (в случае, если в результате последнего выполненного SQL-предписания БД не была открыта в режиме ReadOnly). При работе тренажера ведется и выдается на экран статистика выполнения SQL-предписаний, протоколирование в файл не предусмотрено. Общий вид экрана при работе с тренажером SQL_1 приведен ниже на рис.2.2.
- 55 -
Рис.2.2. Копия экрана дисплея при функционировании модуля SQL_1
Работающие на тренажере могут убедиться в наличии в текущем каталоге тренажера временных (начинающихся символом ‘подчеркивание’) файлов, являющимися результатом последнего выполненного SQL-запроса; при штатном окончании Windows-приложения эти файлы стираются. Пользователь вводит текст SQL-директивы в соответствующем окне и нажимает кнопку ВЫПОЛНИТЬ, после чего в таблице индицируется результат SQL-запроса или выдается предупреждение о невозможности выполнения. Кнопка ПОКАЗАТЬ ВСЮ ТАБЛИЦУ служит для вывода всех записей таблицы ЕМР, при этом (неявно) выполняется SQL-предписание SELECT * FROM 'emp'. Заметим, что в данной реализации SQL имена таблиц следует заключать в кавычки, для наименований полей (вместе с конкретизирующим данное поле именем таблицы) кавычки не требуются. Пользуясь линейкой управления, можно дополнять / изменять / уничтожать записи (если до этого таблица не была открыта в режиме ReadOnly). Пользуйтесь выдаваемыми системой всплывающими подсказками (инициируются при нахождении указателя 'мыши' над отдельными элементами экрана в течение нескольких секунд). 2.2.2.Тренажер SQL-запросов к двум таблицам
- 56 -
Исполняемый файл данного тренажера имеет название SQL_2.EXE, при работе используется ранее описанная таблица ЕМР и таблица DEPT (строение таблицы DEPT приведено выше), алиас DEPT. Общий вид экрана при работе с тренажером SQL_2 приведен ниже на рис.2.3. Условно экран разбит на 2 области - в верхней вводятся SQLдирективы и просматривается результат их выполнения (в окне 'РЕЗУЛЬТИРУЮЩАЯ ТАБЛИЦА), в нижней показаны исходные таблицы DEPT и ЕМР (допускается их редактирование с помощью линеек управления). Пользователь вводит текст SQL-директивы в соответствующем окне и нажимает кнопку ВЫПОЛНИТЬ, после чего в окне РЕЗУЛЬТИРУЮЩАЯ ТАБЛИЦА индицируется результат SQL-запроса или выдается предупреждение о невозможности выполнения. SQL-выражение запоминается в дисковом файле с расширением SQL_2.SQL и восстанавливается при перестартовке тренажера. Примеры SQL-запросов к таблицам DEP и ЕМР приведен выше. Заметим, что при использовании поля HIREDATE следует применять встроенные функции DAY(), MONTH(), YEAR(); подробнее см. контекстный HELP. Точка с запятой в конце SQL-строки необязательна. Локальный SQL поддерживает псевдонимы внутри SQL-выражений (см. ниже задаваемые в клаузе FROM псевдонимы D и Е для таблиц DEPT и ЕМР соответственно). SELECT D.deptno,D.dname,D.loc,E.ename,E.job,E.hiredate,E.sal,E.comm FROM 'dept' D, 'emp' E WHERE D.deptno = E.deptno ORDER BY E.sal
- 57 -
Рис.2.3.Копия экрана дисплея при функционировании модуля SQL_2
Пользователь может и должен самостоятельно составить SQL-запросы для уточнения возможностей локального SQL. 2.2.3.Утилита dbEXPLORER разработки АО ROSNO В комплект программного обеспечения для исследования БД входит разработанная и бесплатно распространяемая АО ROSNO утилита dbEXPLORER ('исследователь' БД). Утилита позволяет подключаться к таблице (файлу) БД по известному алиасу, просматривать содержимое БД (и выполнять допустимые SQL-запросы), получать информацию о полях и их типах в выбранной БД. Утилита dbEXPLORER по функциональности приближается к (штатной) утилите SQL Explorer (см. ниже) и приводится здесь в качестве иллюстрации возможностей создания системного ПО с помощью интегрированных сред Delphi / C++Builder. Принцип взаимодействия пользователя с dbEXPLORER является стандартным для Windows, ввод и выполнение SQLзапросов практически не отличается от вышеописанного.
- 58 -
Рис.2.3.Копия экрана дисплея при функционировании утилиты dbEXPLORER (русификация FREEWARE-продукта АО ROSNO)
Автор данного пособия заочно благодарен разработчикам dbEXPLORER'a и обязан сообщить о внесенных им несущественных изменениях в исходные тексты dbEXPLORER’а (в основном оформительского характера), не затрагивающих сущности утилиты. 2.3.Дополнительные инструментальные средства пакетов Delphi / C++Builder Для операций с БД в составе систем Delphi / C++Builder штатно поставляется набор утилит, приведенных ниже: 1. Database Desktop - программа создания и редактирования таблиц, SQLзапросов и запросов типа QBE (Query By Example, запросов по образцу). 2. Borland Database Engine (BDE) - набор динамических библиотек и драйверов, предназначенных для организации доступа к БД. 3. BDE Administrator - утилита конфигурации BDE, позволяющая настраивать различные параметры BDE. 4. SQL Explorer - утилита для просмотра и редактирования БД и словарей данных.
- 59 -
5. SQL Monitor - программа-монитор для отслеживания порядка выполнения SQL-запросов к удаленным БД. 6. SQL Builder - программа визуального конструирования SQL-запросов. 7. Data Pump - программа для переноса данных между БД различного формата. 8. Local InterBase Server - локальная версия SQL-сервера Borland InterBase. 9. InterBase Server for Windows - многопользовательская версия SQLсервера Borland InterBase. 10.InterBase Server Manager - программа-администратор управления удаленным сервером. 11.SQL Links - набор драйверов для обращения к удаленным промышленным СУБД (Oracle, Microsoft SQL Server). Для доступа к серверу InterBase достаточно возможностей вышеописанного BDE. ЗАКЛЮЧЕНИЕ Приведенное учебное пособие по применению языка запросов SQL позволяет обучаемому начать изучение системы и создавать не слишком сложные программы. Для углубления знаний и навыков следует практиковаться при работе с конкретной системой (например, C++Builder, Delphi, Oracle etc) и пользоваться дополнительной литературой. СПИСОК ЛИТЕРАТУРЫ 1. Грабер M. SQL. -M.: Лори, 2001. -643 C. 2. Пейдж В. Использование ORACLE 8/8i (специальное издание). -М.: Диалектика, 1999. -464 C. 3. Мещеряков Е.В., Хомоненко А.Д. Публикация баз данных в Интернете. CПб.: BHV-Петербург, 2001. -560 С. 4. Codd E.F. Normalized database structure: A brief tutorial. ACM SIGFIDET Workshop on datadescription, access and control. Nov. 1971. 5. Мaier D. The Theory of Relational Databases. ComputerScience Press, 1983. 6. Гофман В., Хомоненко А. Delphi 5. -CПб.: BHV-Петербург, 2000. -800 С. 7. Елманова Н.З.Borland С++Builder. -М.: Диалог-МИФИ, 1998. - 240 C. 8. TUXEDO System: разработка систем клиент-сервер. Ладыженский Г.М.. В сб. 'Системы управления базами данных', 1996. № 1,2.
Учебное издание.
- 60 -
Баканов Валерий Михайлович
Введение в язык SQL запросов к базам данных. Учебное пособие.
Подписано в печать 7.03.2002 г. Формат 60 × 84 1/16. Объем 4 п.л. Тираж 300 экз. Заказ 31.
Отпечатано в типографии Московской государственной академии приборостроения и информатики. 107846, Москва, ул.Стромынка,20.