Теоретические сведения о восходящем проектировании
Выбери формат для чтения
Загружаем конспект в формате docx
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Приложение 1
Теоретические сведения о восходящем проектировании
1. Общие сведения
Проектирование БД на основе описания предметной области в виде сводной таблицы предполагает выявление необходимого набора атрибутов – характеристических свойств объектов таким образом, чтобы каждый из этих атрибутов имел в базе данных уникальное имя, и представление этих атрибутов в виде двумерной таблицы.
В общем случае такие сводные таблицы характеризуются тем, что на пересечении строки и столбца могут иметь более одного значения атрибута. Например, если сводная таблица, описывающая процесс работы над проектами, содержит атрибуты Руководитель Проекта и Исполнитель Проекта, то для отдельного Проекта в графе Исполнитель Проекта должны быть перечислены все сотрудники, работающие над данным проектом (рис. П.1.1.).
№ Проекта
Руководитель Проекта
Исполнитель Проекта
П12.1
Самойлов Ю.В.
Иванов И.И.
Мальцев К.Н.
Петров А.К.
Рис.П.1.1. Пример сводной таблицы
Такой вариант таблицы не является отношением, так как содержит не атомарные значения на пересечении строки и столбца.
Для преобразования данных сводной таблицы в отношение необходимо реконструировать таблицу, например, с помощью простого процесса вставки, результат которой показан на рис.П.1.2.
№ Проекта
Руководитель Проекта
Исполнитель Проекта
П12.1
Самойлов Ю.В.
Иванов И.И.
П12.1
Самойлов Ю.В.
Мальцев К.Н.
П12.1
Самойлов Ю.В.
Петров А.К.
Рис.П.1.2. Пример реляционной таблицы
Однако очевидно, что такое преобразование приводит к возникновению большого объема избыточных данных.
Полученное в результате преобразования данных отношение называют универсальным отношением проектируемой БД. В одно универсальное отношение включаются все представляющие интерес атрибуты, и оно может содержать все данные, которые предполагается размещать в БД в будущем. При проектировании некоторых БД универсальное отношение может использоваться в качестве отправной точки.
Вместе с тем при использовании универсального отношения возникает проблема избыточности данных: значения столбцов таблицы многократно повторяются; могут повторяться также и некоторые наборы значений столбцов.
При работе с отношениями, содержащими избыточные данные, могут возникать проблемы, которые называются аномалиями обновления и подразделяются на аномалии вставки, аномалии удаления и аномалии модификации.
Аномалии вставки. В реляционную таблицу рис.П.1.2 нельзя добавить, например, информацию о новом сотруднике, если он еще не участвует ни в одном проекте. С другой стороны, добавление нового сотрудника, как участника одного из проектов, потребует обязательного дублирования сведений о руководителе проекта, что ведет к потенциальной несовместимости данных (в случае ошибок при вводе).
Аномалии удаления. При удалении из реляционной таблицы рис.П.1.2 информации о сотрудниках, работающих над конкретным проектом (например, при смене команды), будет полностью удалена информация о самом проекте.
Аномалии модификации. Вызывают потенциальную противоречивость данных, которая возникает при вводе повторяющихся данных (в случае ошибочного ввода в одно или несколько значений), а также при редактировании повторяющихся данных.
Перечисленных аномалий можно избежать путем нормализации исходного отношения.
Процесс нормализации – это декомпозиция таблицы на две или более с целью ликвидации дублирования данных и потенциальной их противоречивости. Окончательная цель нормализации сводится к получению такого проекта базы данных, в котором «каждый факт появляется лишь в одном месте».
2. Функциональные зависимости
В основе процесса нормализации лежит концепция функциональной зависимости. Функциональная зависимость описывает связь между атрибутами отношения: если в отношении R, содержащем атрибуты A и B, атрибут B функционально зависит от атрибута A, то каждое отдельное значение атрибута A связано только с одним значением атрибута B (причем в качестве A и B могут выступать группы атрибутов). Атрибут или группа атрибутов A называются при этом детерминантом функциональной зависимости.
Таким образом, при наличии функциональной зависимости A→B кортежи (строки), имеющие одинаковое значение атрибута A, совпадают и по значению атрибута B. Однако обратное не верно: одно и то же значение атрибута B может соответствовать разным значениям атрибута A. Например, из функциональной зависимости Сотрудник→Должность следует, что везде, где будет указываться сотрудник «Еремеев В.К.», ему будет соответствовать должность «Профессор», но должность «Профессор» могут иметь и другие сотрудники.
Функциональная зависимость A→B является полной функциональной зависимостью, если удаление какого-либо атрибута из группы атрибутов A приводит к потере этой зависимости. Функциональная зависимость A→B является частичной функциональной зависимостью, если в группе атрибутов A есть один или несколько атрибутов, при удалении которых эта зависимость сохраняется.
Если для атрибутов A, B и C некоторого отношения существуют функциональные зависимости A→B, B→C, говорят, что атрибут C связан транзитивной зависимостью с атрибутом A через атрибут B (при этом атрибут A не должен функционально зависеть ни от атрибута B, ни от атрибута C).
3. Нормальные формы
На каждом этапе нормализации каждое из отношений находится в одной из так называемых нормальных форм. Нормальные формы (от самой младшей до самой старшей) связаны операцией включения, т.е. более старшая нормальная форма обладает свойствами всех предшествующих и дополнительно имеет свои отличительные признаки.
Нормализация представляет собой формальный метод анализа отношений на основе выявления первичного ключа и существующих функциональных зависимостей. Последовательное удаление частичных функциональных зависимостей и транзитивных зависимостей осуществляется путем декомпозиции отношений и перевода их в следующую (более старшую) нормальную форму.
Реляционная таблица находится в первой нормальной форме (1НФ), если
• каждое значение любого ее атрибута является атомарным;
• в таблице отсутствуют одинаковые строки;
• каждый столбец уникально поименован именем атрибута и содержит текущее значение этого атрибута;
• каждый атрибут ассоциирован с определенным доменом (типом данных).
Реляционная таблица, находящаяся в 1НФ, имеет первичный ключ – атрибут или совокупность атрибутов, значения которых уникально характеризуют каждую запись.
Реляционная таблица находится во второй нормальной форме (2НФ), если она удовлетворяет определению 1НФ и все ее атрибуты, не входящие в первичный ключ, связаны полной функциональной зависимостью с первичным ключом.
Реляционная таблица находится в третьей нормальной форме (3НФ), если она удовлетворяет определению 2НФ и ни один из ее не ключевых атрибутов не связан транзитивной функциональной зависимостью с первичным ключом (т.е. ни один из не ключевых атрибутов не связан функциональной зависимостью с любым другим не ключевым атрибутом).
Таблица находится в третьей нормальной форме Бойса-Кодда (НФБК) (усиленная третья нормальная форма) тогда и только тогда, когда любая функциональная зависимость между ее атрибутами сводится к полной функциональной зависимости от возможного первичного ключа (т.е. все детерминанты отношения являются потенциальными первичными ключами).
Обычно на практике довольствуются приведением реляционной БД к 3НФ или к НФБК, поэтому здесь не будем рассматривать более старшие нормальные формы.
4. Процедура нормализации
Процедура приведения таблиц к 3НФ основывается на том, что единственными функциональными зависимостями в любой таблице должны быть зависимости вида А→K, где K - первичный ключ, а А - некоторый атрибут. Цель нормализации состоит в удалении других функциональных зависимостей.
Возможны два случая:
1. Таблица имеет составной первичный ключ, например, (К1,К2), и включает также атрибут А, который функционально зависит от части этого ключа (например, от К2), но не от полного ключа. В этом случае рекомендуется сформировать другую таблицу, содержащую атрибуты К2 и А (первичный ключ - К2), и удалить атрибут А из первоначальной таблицы:
2. Таблица имеет первичный (возможный) ключ К, атрибут А1, который не является возможным ключом, но функционально зависит от К, и другой не ключевой атрибут А2, который функционально зависит от А1. Решение здесь, по существу, то же самое, что и прежде - формируется другая таблица, содержащая атрибуты А1 и А2, с первичным ключом А1, а атрибут А2 удаляется из первоначальной таблицы.
Таким образом, повторяя применение двух рассмотренных правил, для любой заданной таблицы почти во всех реальных практических ситуациях можно получить в конечном счете множество таблиц, которые находятся в 3НФ или НФБК и не содержат каких-либо функциональных зависимостей вида, отличного от А→К.
Приведем пример применения сформулированных правил для полной нормализации универсального отношения.
Рассмотрим предметную область «Проектная организация». Проектная организация заключает Договоры с Заказчиками на выполнение проектов. По одному Договору может выполняться более одного проекта. Суммарная стоимость договора определяется стоимостью всех проектных работ, выполняемых для этого договора. Каждый договор имеет руководителя. Над каждым Проектом работает группа сотрудников (один из них руководит Проектом), причем это могут быть сотрудники не только одного отдела.
Данные предметной области можно представить в виде сводной таблицы (рис.П.1.3), ориентированной на перечень проектов, ведущихся в организации, с указанием всех их характеристик. В таблице будут следующие столбцы:
• Проект - уникальный идентификатор проекта (например, его номер или название);
• Дата_начало_П - дата начала работы над проектом;
• Дата_конец_П – дата завершения работы над проектом;
• Руководитель_П – ФИО руководителя проекта (будем считать, что это уникальная идентификация для предметной области);
• Должность_РП – должность руководителя проекта;
• Отдел_РП – отдел (номер или название), в котором работает руководитель проекта;
• Стоимость_П – стоимость проекта;
• Договор – уникальный идентификатор договора (например, его номер внутри организации), в рамках которого выполняется проект;
• Руководитель_Д – ФИО руководителя договора (уникальная идентификация для предметной области);
• Дата_начало_Д – дата заключения договора;
• Дата_конец_Д – дата окончания действия договора;
• Исполнитель_П – перечень всех исполнителей проекта (каждый исполнитель уникально характеризуется фамилией, именем и отчеством);
• Должность_ИП – должности исполнителей проекта (соответственно для каждого исполнителя);
• Отдел_ИП – отделы, в которых работают исполнители проекта (соответственно для каждого исполнителя).
Для того чтобы преобразовать эту таблицу в реляционное отношение, находящееся в 1НФ, необходимо в каждой строке продублировать все данные о проекте для каждого из исполнителей проекта. При этом будут повторяться и данные о договоре для каждого из проектов, исполняемых по одному договору.
Назовем полученное реляционное отношение «Работа над проектом» (рис.П.1.4).
Проект
Дата_ начало_П
Дата_ конец_П
Руководитель_П
Должность_РП
Отдел_РП
Стоимость_П
Договор
Руководитель_Д
Дата_ начало_Д
Дата_ конец_Д
Исполнитель_П
Должность_ИП
Отдел_ИП
П12.1
01.02.05
20.04.05
Самойлов Ю.В.
зав. отделом
1
30000
Д12
Бирюков Р.Л.
20.01.05
01.06.05
Иванов И.И.
конструктор
1
Мальцев К.Н.
инженер
1
Петров А.К.
техник
2
Рис.П.1.3. Сводная таблица данных предметной области
Проект
Дата_
начало_П
Дата_ конец_П
Руководитель_П
Должность_РП
Отдел_РП
Стоимость_П
Договор
Руководитель_Д
Дата_ начало_Д
Дата_ конец_Д
Исполнитель_П
Должность_ИП
Отдел_ИП
П12.1
01.02.05
20.04.05
Самойлов Ю.В.
зав. отделом
1
30000
Д12
Бирюков Р.Л.
20.01.05
01.06.05
Иванов И.И.
конструктор
1
П12.1
01.02.05
20.04.05
Самойлов Ю.В.
зав. отделом
1
30000
Д12
Бирюков Р.Л.
20.01.05
01.06.05
Мальцев К.Н.
инженер
1
П12.1
01.02.05
20.04.05
Самойлов Ю.В.
зав. отделом
1
30000
Д12
Бирюков Р.Л.
20.01.05
01.06.05
Петров А.К.
техник
2
Рис.П.1.4. Реляционное отношение «Работа над проектом»
1. Выявление первичного ключа отношения.
В качестве первичного ключа полученного реляционного отношения, очевидно, выступает совокупность атрибутов Проект (уникальная идентификация проекта) и Исполнитель_П (уникальная идентификация исполнителя проекта). Значения этих двух атрибутов являются необходимыми и достаточными для уникальной идентификации каждой строки таблицы.
Работа_над_Проектом (Проект, Дата_начало_П, Дата_конец_П,
Руководитель_П, Должность_РП, Отдел_РП,
Стоимость_П, Договор,
Руководитель_Д, Дата_начало_Д, Дата_конец_Д,
Исполнитель_П, Должность_ИП, Отдел_ИП)
2. Выявление атрибутов, функционально зависящих от части составного первичного ключа.
Все атрибуты отношения можно разделить на две группы – атрибуты, характеризующие Проект, и атрибуты, характеризующие Исполнителя. Атрибуты каждой из групп функционально зависят от части первичного ключа: атрибуты, характеризующие Проект, зависят от значения атрибута Проект, а атрибуты, характеризующие Исполнителя, зависят от значения атрибута Исполнитель_П. Таким образом, из исходного отношения необходимо выделить две проекции – отношение «Проект» с первичным ключом Проект и отношение «Исполнитель» с первичным ключом Исполнитель_П :
Проект (Проект, Дата_начало_П, Дата_конец_П, Руководитель_П,
Должность_РП, Отдел_РП, Стоимость_П, Договор,
Руководитель_Д, Дата_начало_Д, Дата_конец_Д)
Исполнитель (Исполнитель_П, Должность_ИП, Отдел_ИП)
Из исходного отношения при этом удаляются все атрибуты кроме атрибутов первичного ключа:
Работа_над_Проектом (Проект, Исполнитель_П)
3. Ликвидация функциональных зависимостей между не ключевыми атрибутами
Полученное отношение «Проект» не находится в 3НФ, т.к. включает
1) атрибуты Должность_РП, Отдел_РП, функционально зависящие от не ключевого атрибута Руководитель_П ;
2) атрибуты Руководитель_Д, Дата_начало_Д, Дата_конец_Д, функционально зависящие от не ключевого атрибута Договор.
Применим Шаг 2 процедуры нормализации к отношению «Проект» и получим следующую декомпозицию:
Проект (Проект, Дата_начало_П, Дата_конец_П, Руководитель_П,
Стоимость_П, Договор)
Руководитель (Руководитель_П, Должность_РП, Отдел_РП)
Договор (Договор, Руководитель_Д, Дата_начало_Д, Дата_конец_Д)
Итак, декомпозиция исходного отношения включает следующие проекции:
Работа_над_Проектом (Проект, Исполнитель_П)
Проект (Проект, Дата_начало_П, Дата_конец_П, Руководитель_П,
Стоимость_П, Договор)
Договор (Договор, Руководитель_Д, Дата_начало_Д, Дата_конец_Д)
Руководитель (Руководитель_П, Должность_РП, Отдел_РП)
Исполнитель (Исполнитель_П, Должность_ИП, Отдел_ИП)
Такой декомпозиции достаточно для того, чтобы преобразовать исходное отношение к совокупности нормализованных отношений (все полученные таблицы приведены к 3НФ).
Однако в декомпозиции получилось два однотипных отношения: «Исполнитель» и «Руководитель». Улучшить вариант БД можно, объединив эти отношения в одно отношение «Сотрудник»:
Проект (Проект, Дата_начало_П, Дата_конец_П,
Сотрудник, Стоимость_П, Договор)
Договор (Договор, Сотрудник,
Дата_начало_Д, Дата_конец_Д)
Сотрудник (Сотрудник, Должность, Отдел)
Работа_над_Проектом (Проект, Сотрудник)
В такой структуре атрибут «Сотрудник» в отношении «Проект» содержит сведения о руководителях проектов; в отношении «Договор» - сведения о руководителях договоров; в отношении «Работа_над_Проектом» - сведения об исполнителях проектов.
Приложение 2
Извлечение данных с помощью языка SQL – команда SELECT
Назначение оператора SELECT состоит в выборке и отображении данных одной или более таблиц базы данных. Оператор SELECT является чаще всего используемой командой языка SQL. Общий формат оператора SELECT имеет следующий вид:
SELECT [ALL | DISTINCT]
<список данных>
FROM <список таблиц>
[WHERE <условие выборки>]
[GROUP BY <имя столбца> [,<имя столбца>] ... ]
[HAVING <условие поиска>]
[ORDER BY <спецификация> [,<спецификация>] ...]
Обработка элементов оператора select выполняется в следующей последовательности:
From - определяются имена используемой таблицы или нескольких таблиц
Where – выполняется фильтрация строк объекта в соответствии с заданными условиями
Group by – образуются группы строк, имеющих одно и то же значение в указанном столбце
Having – фильтруются группы строк объекта в соответствии с указанным условием
Select – устанавливается, какие столбцы должны присутствовать в выходных данных
Order by – определяется упорядоченность результатов выполнения операторов
Порядок предложений и фраз в операторе SELECT не может быть изменен. Только двa предложения оператора — SELECT и FROM — являются обязательными, все остальные предложения и фразы могут быть опущены. Операция SELECT является закрытой: результат запроса к таблице представляет собой другую таблицу.
Использование обобщающих функций языка SQL
Стандарт ISO содержит определение следующих пяти обобщающих функций.
COUNT
Возвращает количество значений в указанном столбце
SUM
Возвращает сумму значений в указанном столбце
AVG
Возвращает усредненное значение в указанном столбце
MIN
Возвращает минимальное значение в указанном столбце
MAX
Возвращает максимальное значение в указанном столбце
Все эти функции оперируют со значениями в единственном столбце таблицы и возвращают единственное значение. Функции COUNT, MIN и МАХ применимы как к числовым, так и к нечисловым полям, тогда как функции SUM и AVG могут использоваться только в случае числовых полей. За исключением COUNT(*), при вычислении результатов любых функции сначала исключаются все пустые значения, после чего требуемая операция применяется только к оставшимся конкретным значениям столбца. Вариант COUNT(*) является особым случаем использования функции COUNT — его назначение состоит в подсчете всех строк в результирующей таблице, независимо от того, содержатся там пустые, дублирующиеся или любые другие значения.
Пример:
SELECT COUNT(*) AS count
FROM property_for_rent
WHERE rent>350
Предложение WHERE
Очень часто требуется тем или иным образом ограничить набор строк, помещаемых в результирующую таблицу запроса. Это достигается с помощью указания в запросе предложения WHERE. Оно состоит из ключевого слова WHERE, за которым следует перечень условий поиска, определяющих те стройки, которые должны быть выбраны при выполнении запроса. Существует пять основных типов условий поиска (или предикатов, если пользоваться терминологией ISO).
• Сравнение. Сравниваются результаты вычисления одного выражения с результатами вычисления другого выражения.
• Диапазон. Проверяется, попадает ли результат вычисления выражения в заданный диапазон значений.
• Принадлежность к множеству. Проверяется, принадлежит ли результат вычисления выражения к заданному множеству значений.
• Соответствие шаблону. Проверяется, отвечает ли некоторое строковое значение заданному шаблону.
• Значение NULL. Проверяется, содержит ли данный столбец определитель NULL (неизвестное значение).
Сравнение. В языке SQL можно использовать следующие операторы сравнения:
=
Равенство
<
Меньше
>
Больше
<=
меньше или равно
>=
больше или равно
<>
не равно (стандарт ISO)
!=
не равно (используется в некоторых диалектах)
Более сложные предикаты могут быть построены с помощью логических операторов AND, OR или NOT, а также с помощью скобок, используемых для определения порядка вычисления выражения (если это необходимо или желательно). Вычисление выражений в условиях выполняется по следующим правилам.
• Выражение вычисляется слева направо.
• Первыми вычисляются подвыражения в скобках.
• Операторы NOT выполняются до выполнения операторов AND и OR.
• Операторы AND выполняются до выполнения операторов OR.
Для устранения любой возможной неоднозначности рекомендуется использовать скобки.
Диапазон. Наличие ключевого слова BETWEEN требует задания границ диапазона значений. Имеется и негативная версия проверки диапазона значений (NOT BETWEEN). В этом случае требуется, чтобы проверяемое значение лежало вне границ заданного диапазона. Наличие ключевого слова BETWEEN и соответствующей проверки лишь незначительно повышает выразительную мощность языка SQL, поскольку те же самые результаты могут быть достигнуты с помощью выполнения двух обычных проверок. (salary BETWEEN 20000 AND 30000 аналогично salary > = 20000 AND salary < = 30000). Однако многие полагают, что проверка вхождения в диапазон с помощью ключевого слова BETWEEN является более простым способом записи условий выборки, чем обычные проверки.
Принадлежность к множеству. Проверка вхождения результата вычисления выражения в заданное множество организуется с помощью ключевого слова IN. При этом проверяется, соответствует ли результат вычисления выражения одному из значений в предоставленном списке. Существует и отрицательная версия этой проверки (NOT IN), которая используется для отбора любых значений, кроме тех, которые указаны в представленном списке. Как и в случае ключевого слова BETWEEN, условие IN незначительно повышает выразительную мощность языка SQL (position IN ('Manager', 'Deputy') аналогично position = 'Manager' OR position = 'Deputy'). Однако использование ключевого слова IN представляет собой более эффективный способ записи условий поиска, особенно если набор допустимых значений достаточно велик.
Соответствие шаблону. В SQL существует два специальных символа шаблона, используемых при проверке символьных значений:
% - (процент) – любая последовательность из 0 и более символов
_ - (подчеркивание) – любой одиночный символ
Пример применения операторов:
SELECT *
FROM staff
WHERE address LIKE ‘%Glasgow%’
Значение NULL. Иногда требуется найти пустое значение. Например comment = ' ' или comment < > 'too remote'. Однако оба этих решения ошибочны. Отсутствующий комментарий (значение NULL) рассматривается как неизвестное значение, поэтому его нельзя сравнить на равенство или неравенство с другой строкой. Если попробовать выполнить запрос с любым из приведенных выше условий поиска, то результирующая таблица окажется пустой. Правильное решение состоит в явной проверке на наличие пустого значения, для чего используется специальное ключевое слово IS NULL: comment IS NULL. Отрицательная версия данного условия поиска (IS NOT NULL) может использоваться для проверки присутствия значения в столбце.
Предложение Order by
В общем случае строки в результирующей таблице SQL-запроса не упорядочены каким-либо определенным образом. Однако их можно требуемым образом отсортировать, для чего в оператор SELECT помещается фраза ORDER BY. Фраза ORDER BY включает список разделенных запятыми идентификаторов столбцов, по которым требуется упорядочить результирующую таблицу запроса. Идентификатор столбца может представлять собой либо его имя, либо номер, который идентифицирует элемент списка SELECT его позицией в этом списке. Самый левый элемент списка имеет номер 1, следующий — номер 2 и т.д. Номера столбцов могут использоваться в тех случаях, когда столбцы, по которым следует упорядочить результат, являются вычисляемыми, а фраза AS с указанием имени этого столбца в операторе SELECT отсутствует. Фраза ORDER BY позволяет упорядочить выбранные записи в порядке возрастания (ASC) или убывания (DESC) значений любого столбца или комбинации столбцов независимо от того, присутствуют эти столбцы в таблице результатов или нет.
Во фразе ORDER BY может быть указано и больше одного элемента. Главный ключ сортировки определяет общую упорядоченность строк результирующей таблицы. Если значения главного ключа не уникальны, в результирующей таблице будет присутствовать несколько строк с одним и тем же значением старшего ключа сортировки. В этом случае может оказаться желательным упорядочить строки с одним и тем же значением главного ключа по какому-либо дополнительному ключу сортировки. Если во фразе ORDER BY присутствуют второй и последующие элементы, то такие элементы называют младшими ключами сортировки.
Пример:
SELECT *
FROM staff
ORDER BY salary DESC
Предложение Group By
В итогах все детальные данные отчета сжимаются в одну обобщающую строку. Однако очень часто в отчетах требуется формировать и промежуточные итоги. Для этой ^цели в операторе SELECT может указываться фраза GROUP BY. Запрос, в котором присутствует фраза GROUP BY, называется группирующим запросом, поскольку в нем группируются данные, полученные в результате выполнения операции SELECT, после чего для каждой отдельной группы создается единственная суммарная строка. Столбцы, перечисленные во фразе GROUP BY, называются группируемыми столбцами. Стандарт ISO требует, чтобы предложение SELECT и фраза GROUP BY были тесно связаны между собой. При использовании в операторе SELECT фразы GROUP BY каждый элемент списка в предложении SELECT должен иметь единственное значение для всей группы. Более того, предложение SELECT может включать только следующие типы элементов:
• имена столбцов;
• обобщающие функции;
• константы;
• выражения, включающие комбинации перечисленных выше элементов.
Все имена столбцов, приведенные в списке предложения SELECT, должны присутствовать и во фразе GROUP BY — за исключением случаев, когда имя столбца используется в обобщающей функции. Обратное правило не является справедливым — во фразе GROUP BY могут присутствовать имена столбцов, отсутствующие в списке предложения SELECT. Если совместно с фразой GROUP BY используется предложение WHERE, то оно обрабатывается первым, а группированию подвергаются только те строки, которые удовлетворяют условию поиска.
Стандартом ISO определено, что при проведении группирования все отсутствующие значения рассматриваются как равные. Если две строки таблицы в одном и том же группируемом столбце содержат значения NULL и идентичные значения во всех остальных непустых группируемых столбцах, они помещаются в одну и ту же группу.
Пример:
SUM(salary) AS sum
FROM staff :,
GROUP BY bno
ORDER BY bno;
Концептуально, при обработке этого запроса выполняются следующие действия.
1: Строки таблицы Staff распределяются в группы в соответствии со значениями в столбце номера отделения компании. В пределах каждой из групп оказываются данные обо всем персонале одного из отделений компании. В нашем примере будут созданы три группы.
bno
sno
Salary
Count(sno)
Sum(salary
B3
B3
B3
SG37
SG14
SG5
12000
18000
24000
3
54000
B5
B5
SL21
SL41
30000
9000
2
39000
B7
SA9
9000
1
9000
2: Для каждой из групп вычисляется общее количество строк, равное количеству работников отделения, а также сумма значений в столбце Salary, которая и является интересующей нас суммой заработной платы всех работников отделения. Затем генерируется единственная сводная строка для всей группы исходных строк.
3: Наконец, полученные строки результирующей таблицы пересортировываются в порядке возрастания номера отделения, указанного в столбце Bno.
Предложение HAVING
Фраза Having предназначена для использования совместно с фразой GROUP BY для задания ограничений, указываемых с целью отбора тех групп, которые будут померены в результирующую таблицу запроса. Хотя фраза Having и предложение WHERE имеют сходный синтаксис, их назначение различно. Предложение WHERE предназначено для фильтрации отдельных строк, используемых для группирования или помещаемых в результирующую таблицу запроса, тогда как фраза HAVING используется для фильтрации групп, помещаемых в результирующую таблицу запроса. Стандарт ISO требует, чтобы имена столбцов, используемые во фразе HAVING, обязательно присутствовали в списке фразы GROUP BY или применялись в обобщающих функциях. На практике условия поиска во фразе HAVING всегда включают, по меньшей мере, одну обобщающую функцию, в противном случае эти условия поиска должны быть померены в предложение WHERE и применяться для отбора отдельных строк.
Фраза HAVING не является необходимой частью языка SQL — любой запрос, написанный с использованием фразы HAVING, может быть представлен в ином виде, без ее применения.
Подзапросы
Подзапрос - законченный операторов SELECT, внедренный в тело другого оператора SELECT. Внешний (второй) оператор SELECT использует результат выполнения внутреннего (первого) оператора для определения содержания окончательного результата всей операции. Внутренние запросы могут быть помещены в предложения WHERE и HAVING внешнего оператора SELECT — в этом случае они получают название подзапросов, или вложенных запросов. Кроме того, внутренние операторы SELECT могут использоваться в операторах INSERT, UPDATE и DELETE. Существует три типа подзапросов.
• Скалярный подзапрос возвращает значение, выбираемое из пересечения одного столбца с одной строкой, — т.е. единственное значение. В принципе, скалярный подзапрос может использоваться везде, где требуется указать единственное значение.
SELECT sno, fname, Inaroe, position
FROM staff
WHERE bno =
(SELECT bno
FROM branch
WHERE street = '163 Main St')
• Строковый подзапрос возвращает значения нескольких столбцов таблицы, но в виде единственной строки. Строковый подзапрос может использоваться везде, где применяется конструктор строковых значений — обычно это предикаты.
SELECT pno, street, area, city, pcode, type, rooms, rent
FROM property_for_rent
WHERE sno IN
(SELECT sno
FROM staff
WHERE bno =
(SELECT bno
FROM branch
WHERE street = '163 Main St'));
• Табличный подзапрос возвращает значения одного или больше столбцов таблицы, размещенные в более чем одной строке. Табличный подзапрос может использоваться везде, где допускается указывать таблицу — например, как операнд предиката IN.
Подзапрос представляет собой инструмент создания временной таблицы, содержимое которой извлекается и обрабатывается внешним оператором. Подзапрос может указываться непосредственно после операторов сравнения (т.е. операторов =, <, >, <=, >=, о) в предложениях WHERE и HAVING. Текст подзапроса должен быть заключен в скобки.
К подзапросам применяются следующие правила и ограничения.
1. В подзапросах не должна использоваться фраза ORDER BY, хотя она может присутствовать во внешнем запросе.
2. Список в предложении SELECT подзапроса должен состоять из имен отдельных столбцов или составленных из них выражений — за исключением случая, когда в подзапросе используется ключевое слово EXISTS.
3. По умолчанию имена столбцов в подзапросе относятся к таблице, имя которой указано в его предложении FROM. Однако допускается ссылаться и на столбцы таблицы, указанной во фразе FROM внешнего запроса, для чего используются квалифицированные имена столбцов.
4. Если подзапрос является одним из двух операндов, участвующих в операции сравнения, то запрос должен указываться в правой части этой операции. Например, приведенный ниже вариант записи запроса является некорректным, поскольку подзапрос размещен в левой части операции сравнения со значением столбца Salary:
SELECT sno, fname, lname, position, salary
FROM staff
WHERE (SELECT avg(salary) FROM staff) < salary;
Корректная запись запроса (Составьте список всех сотрудников, имеющих зарплату выше средней указав то, насколько их зарплата превышает среднюю зарплату по предприятию):
SELECT sno, fname, Iname, position, salary - (SELECT avg(salary) FROM staff)
AS sal_diff
FROM staff
WHERE salary >
I (SELECT avg(salary)
FROM staff);
Ключевые слова ANY и ALL
Ключевые слова ANY и ALL могут использоваться с подзапросами, возвращающими один столбец чисел. Если подзапросу будет предшествовать ключевое слово ALL, условие сравнения считается выполненным только в том случае, если оно выполняется для всех значений в результирующем столбце подзапроса. Если записи подзапроса предшествует ключевое слово ANY, то условие сравнения будет считаться выполненным, если оно выполняется хотя бы для одного из значений в результирующем столбце подзапроса. Если результате выполнения подзапроса будет получено пустое значение, то для ключевого слова ALL условие сравнения будет считаться выполненным, а для ключевого слова АNY — невыполненным. Согласно стандарту ISO дополнительно можно использовать ключевое слово SOME, являющееся синонимом ключевого слова ANY.
Пример. Найдите всех работников, чья зарплата превышает зарплату хотя бы одного Шработника отделения компании под номером *ВЗ*.
SELECT sno, fname, Iname, position, salary
FROM staff
WHERE salary > SOME
(SELECT salary
FROM staff
WHERE bno = 'B3');
Многотабличные запросы
Для того чтобы объединить в результирующей таблице столбцы из нескольких исходных таблиц, необходимо L. выполнить операцию соединения. В языке SQL операция соединения используется для объединения информации из двух таблиц посредством образования пар связанных строк, выбранных из каждой таблицы. Помещаемые в объединенную таблицу пары строк составляются по равенству входящих в них значений указанных столбцов.
Если необходимо получить информацию более чем из одной таблицы, то можно либо применить подзапрос, либо выполнить соединение таблиц. Если результирующая таблица запроса должна содержать столбцы из разных исходных таблиц, то целесообразно использовать механизм соединения таблиц. Для выполнения соединения достаточно в предложении FROM указать имена двух и более таблиц, разделив их запятыми, после чего включить в запрос предложение WHERE с определением столбцов, используемых для соединения указанных таблиц. Кроме того, вместо имен таблиц можно использовать назначенные им в предложении FROM псевдонимы (алиасы). В этом случае имена таблиц и назначаемые им псевдонимы должны разделяться пробелами. Псевдонимы могут использоваться с целью квалификации имен столбцов во всех тех случаях, когда возможно появление неоднозначности. Кроме того, псевдонимы могут использоваться как сокращения имен таблиц. Если для таблицы определен псевдоним, он может использоваться в любом месте, где требуется указание имени этой таблицы. Это условие определяется посредством задания условия поиска r.rno=v.rno. Подобные столбцы исходных таблиц называют сочетаемыми столбцами.
Чаще всего многотабличные запросы выполняются для двух таблиц, соединенных связью типа 1:М. Пары строк, которые генерируются при выполнении запроса, представляют собой результат всех допустимых комбинаций строк дочерней и родительской таблиц.
Стандарт SQL2 дополнительно предоставляет следующие способы определения данного соединения:
FROM renter r JOIN viewing v ON r.rno = v.rno
FROM renter JOIN viewing USING rno
FROM renter NATURAL JOIN viewing
В каждом случае предложение FROM замещает исходные предложения FROM и WHERE. Однако в первом варианте создается таблица с двумя идентичными столбцам Rno, тогда как в остальных двух случаях результирующая таблица будет содержать только один столбец Rno.
Выполнение соединений
Соединение является подмножеством более общей комбинации данных двух таблиц, называемой их декартовым произведением (см. раздел 3.4.1). Декартово произведение двух таблиц представляет собой другую таблицу, состоящую из всех возможных пар строк, входящих в состав обеих таблиц. Набор столбцов результирующей таблицы представляет собой все столбцы первой таблицы, за которыми следуют все столбцы второй таблицы. Если ввести запрос к двум таблицам без задания предложения WHERE, результат выполнения запроса в среде SQL будет представлять собой декартово произведение содержимого этих таблиц. Кроме того, стандарт ISO предусматривает специальный формат оператора SELECT, позволяющий вычислить декартово произведение двух таблиц:
SELECT [DISTINCT | ALL] {* | column_list}
FROM table namel CROSS JOIN table name2
Процедура генерации результирующей таблицы содержащего соединение операто pa SELECT состоит в следующем.
1. Формируется декартово произведение таблиц, указанных в предложении FROM.
2. Если в запросе присутствует предложение WHERE, применение условий поиска к каждой строке таблицы производится с сохранением в таблице только тех строк, которые удовлетворяют заданным условиям. В терминах реляционной алгебры эта операция называется ограничением декартового произведения.
3. Для каждой оставшейся строки определяется значение каждого элемента, указанного в списке предложения SELECT, в результате чего формируется отдельная строка результирующей таблицы.
4. Если в исходном запросе присутствует фраза SELECT DISTINCT, из результирующей таблицы удаляются все строки-дубли. В реляционной алгебре действия, выполняемые на 3 и 4 этапах, эквивалентны операции проекции по столбцам, заданным в списке предложения SELECT.
5. Если выполняемый запрос содержит предложение ODER BY, осуществляется переупорядочивание строк результирующей таблицы.
Открытые соединения
При выполнении операции соединения данные из двух таблиц комбинируются с образованием пар связанных строк, в которых значения сопоставляемых столбцов одинаковые. Если строка одной из таблиц не находит себе соответствия в другой, то она не попадает в результирующий набор данных. Именно это правило применялось во всех рассмотренных выше примерах соединения таблиц. Стандартом ISO предусмотрен и другой набор операторов соединений, называемых открытыми соединениями (см. раздел 3.4.1). При открытом соединении в результирующую таблицу помещаются также строки, не удовлетворяющие условию соединения.
Если в результирующую таблицу потребуется включить и эти не имеющие соответствия строки, то следует использовать открытое соединение. Существует три типа открытых соединений: левое, правое и полное открытое.
Левое соединение:
FROM branchl b LEFT JOIN property_for_rentl p ON b.bclty = p.pcity;
В этом примере за счет применения левого открытого соединения в результирующую таблицу попали не только две строки, в которых имеется соответствие между названиями городов, но также та строка первой из соединяемых таблиц (левой) которая не нашла себе соответствия во второй таблице. В этой строке все поля второй таблицы заполнены значениями NULL.
Правое соединение:
FROM branchl b RIGHT JOIN property for rentl p ON b.bcity = p.pcity;
В этом примере при выполнении правого открытого соединения в результирующую таблицу были включены не только те две строки, которые имеют одинаковые значения в сопоставляемых столбцах, но также и та строка из второй (правой) таблицы, которой не нашлось соответствия в первой (левой) таблице. В этой строке все поля из первой таблицы получили значения NULL.
Полное соединение:
FROM branchl b FULL JOIN property for_rent p ON b.bcity = p.pcity;
В случае полного открытого соединения в результирующую таблицу помещаются не только те две строки, которые имеют одинаковые значения в сопоставляемых столбцах, но и все остальные строки исходных таблиц, не нашедшие себе соответствия. В этих строках все столбцы той таблицы, в которой не было найдено соответствия, заполняются значениями NULL. На момент написания этой книги существовало лишь несколько СУ БД, поддерживавших выполнение запросов с операциями открытых соединений.
Ключевые слова EXISTS и NOT EXIST
Ключевые слова EXISTS и NOT EXISTS предназначены для использования только совместно с подзапросами. Результат их обработки представляет собой логическое значение TRUE или FALSE. Для ключевого слова EXISTS результат равен TRUE в том и только в том случае, если в возвращаемой подзапросом результирующей таблице присутствует хотя бы одна строка. Если результирующая таблица подзапроса пуста, результатом обработки ключевого слова EXISTS будет значение FALSE. Для ключевого слова NOT EXISTS используются правила обработки, обратные по отношению к ключевому слову EXISTS.
SELECT sno, fname, Iname, position FROM staff s
WHERE EXISTS
(SELECT *
FROM branch b
WHERE s.bno = b.bno AND city = 'London');
Приложение 3
Теоретические сведения о нисходящем проектировании
1. Методология концептуального проектирования базы данных
Этап 1. Создание локальной концептуальной модели данных на основе представления о предметной области каждого из типов пользователей
Первый этап проектирования базы данных состоит в разработке концептуальных моделей данных для каждого из существующих типов пользователей создаваемого приложения. Представление пользователя включает в себя данные, необходимые конкретному пользователю для принятия решений или выполнения некоторого задания. Обычно представление пользователя отражает некоторую функциональную область в общем поле деятельности предприятия — например, производство, маркетинг, сбыт, управление кадрами или складской учет. Пользователь может быть как отдельным работником, так и группой лиц, которые будут непосредственно работать с создаваемым приложением. В альтернативном случае понятие "пользователь" может представлять генерируемый системой отчет или даже запрос, связанный с получением результатов транзакции. Суть в том, что в любом случае выполнение требуемых пользователю действий должно обеспечиваться создаваемой системой.
Определить характеристики представлений пользователей можно с помощью различных методов.
1.Начать следует с изучения диаграмм потоков данных, которые к этому моменту уже должны быть созданы. Изучение этих диаграмм позволит установить функциональные области и, возможно, отдельные функции.
2. Затем рекомендуется провести опросы потенциальных пользователей,
3.изучить деловые процедуры,
4.существующие отчеты и формы и/или
5. провести обследование работы предприятия.
Для некоторого представления локальной концептуальной моделью данных мы будем называть концептуальную модель данных, которая отражает представление о предметной области приложения соответствующего пользователя.
Этап 1.1. Определение типов сущностей
Первый этап в построении локальной концептуальной модели данных состоит в определении основных объектов, которые могут интересовать пользователя. Эти объекты являются типами сущностей, входящих в модель.
Этап 1.1.1. Выявление типов сущностей
Один из методов идентификации сущностей состоит в изучении спецификаций по выполнению конкретных функций пользователя на данном предприятии. Из этих спецификаций следует извлечь все используемые в них существительные или сочетания существительного и прилагательного (например, "личный номер", "фамилия работника", "номер объекта недвижимости", "адрес объекта недвижимости", "арендная плата", "количество комнат"). Затем среди них выбираются самые крупные объекты (люди, города) или представляющие интерес концепции и исключаются все существительные, которые просто определяют другие объекты. Например, свойства "личный номер" и "фамилия работника" могут быть объединены в сводном объекте под названием "работник", тогда как свойства "номер объекта недвижимости", "адрес объекта недвижимости", "арендная плата" и "количество комнат" можно объединить в сущности под названием "объект недвижимости".
Альтернативный способ идентификации сущностей состоит в поиске объектов, которые существуют независимо от других. Например, объект "работник" (staff) безусловно является сущностью, потому что любой работник существует независимо от того, знаем мы его имя, адрес и номер телефона или нет. В этой работе существенную помощь могут оказать пользователи создаваемого приложения.
В некоторых случаях выделение сущностей бывает затруднено из-за способа, посредством которого они представлены в спецификациях. Зачастую пользователи, излагая свои мысли, используют примеры или аналогии. Вместо того чтобы вести разговор о некотором обобщенном работнике, они могут просто упомянуть одно или несколько имен. Бывает также, что пользователи заменяют имена работников или название предприятия выполняемыми ими обязанностями или оказываемыми услугами. В этом случае они могут упоминать либо должность работника, либо выполняемые им функции — например, "руководитель", "ответственный", "контролер" или "заместитель".
Чтобы еще больше запутать положение дел, пользователи часто используют синонимы или омонимы. Синонимами называются слова, сходные по смыслу, но различные по звучанию и написанию, — например, "отделение" и "филиал". Омонимы — это слова, одинаковые по написанию и звучанию, но имеющие различные смысловые значения, причем реальное значение в каждом конкретном случае можно установить только по контексту. Так, слово "программа" может обозначать курс обучения, предстоящую серию последовательных событий, план предстоящей работы и даже последовательность телепередач.
Этап 1.1.2. Документирование типов сущностей
После выделения каждой сущности ей следует присвоить некоторое осмысленное имя, которое обязательно должно быть понятно пользователям. Выбранное имя и описание сущности помещается в словарь данных. Если это возможно, следует установить и внести в документацию ожидаемое количество экземпляров каждой сущности. Если сущность известна пользователям под разными именами, все дополнительные имена рекомендуется определить как алиасы (синонимы) и также занести в словарь данных.
Этап 1.2. Определение типов связей
После выделения сущностей следующим этапом разработки будет установление всех существующих между ними связей.
Этап 1.2.1. Определение связей
Одним из методов определения сущностей является выборка всех существительных, присутствующих в спецификациях на проект. Аналогичный подход можно использовать и при определении существующих связей, однако в этом случае выбираются все выражения, в которых содержатся глаголы. Например:
• Подразделение имеет персонал.
• Персонал занимается объектами недвижимости.
• Арендатор просматривает сведения об объектах недвижимости, сдаваемых в аренду.
Тот факт, что текст спецификаций содержит информацию о некоторых связях позволяет предположить, что эти связи являются весьма важными для предприятия, поэтому они обязательно должны быть отображены в создаваемой модели.
Нас интересуют только те связи между сущностями, которые необходимы для удовлетворения требований к проекту.
В большинстве случаев связи являются парными — другими словами, связи существуют только между двумя сущностями. Однако следует проявлять осторожность и тщательно проверять наличие в проекте комплексных связей, объединяющих более двух сущностей различных типов, а также рекурсивных связей, существующих между сущностями одного и того же типа.
Особое внимание следует уделять проверке того, были ли выделены все связи, явно или неявно присутствующее в спецификациях на проект. В принципе, каждую из возможных пар сущностей было бы полезно проверить на наличие между ними некоторой связи может оказаться чрезвычайно трудоемкой. Но вообще отказываться от выполнения подобных проверок неразумно, к тому же ответственность за печальные последствия этого отказа придется нести как аналитикам, так и проектировщикам. Так или иначе, все пропущенные связи будут обязательно выявлены позже, при проведении проверки возможности выполнения транзакций, необходимых пользователям.
Этап 1.2.2. Определение кардинальности связей и ограничений, накладываемых на его участников
Установив связи, которые будут иметь место в создаваемой модели, необходимо определить кардинальность каждой из них. Каждая связь может иметь кардинальность либо "один к одному" (1:1), либо "один ко многим" (1:М), либо "многие ко многим" (М:М). Если известны конкретные значения кардинальности или хотя бы верхний или нижний предел этих значений, то эту информацию обязательно нужно зафиксировать в документации. Кроме того, следует проанализировать степень участия каждой из сущностей в конкретном типе связи. Степень участия может быть либо полной (тотальной), либо частной.
Модель, включающая сведения о кардинальности связей и степени участия в ней сторон, более наглядно отражает смысл установленных связей. Кроме того, кардинальность связи и степень участия в ней сторон представляют собой определенные ограничения, используемые для проверки и поддержания качества данных в базе. Эти ограничения являются теми утверждениями о свойствах экземпляров сущностей, которые могут быть проверены при изменении данных в базе с целью определения того, вызовут ли данные изменения нарушение установленных правил.
Этап 1.2.3. Документирование типов связей
После определения отдельных типов связей им присваиваются осмысленные имена, которые должны быть понятны пользователям. Кроме того, мы рекомендуем помещать в словарь данных развернутое описание каждой связи, включающее сведения о кардинальности и степени участия ее членов.
Этап 1.2.4. Использование средств ER-моделирования
Работа существенно упрощается, если сложная система помимо обширного текстового описания имеет и некоторое визуальное представление. Для представления сущностей и связей между ними обычно используются диаграммы "сущность—связь" (ER-диаграммы).
Этап 1.3. Определение атрибутов и связывание их с типами сущностей и связей
На следующем этапе предлагаемой методологии необходимо выявить все данные, описывающие сущности и связи, выделенные в создаваемой модели базы данных. Воспользуемся тем же методом, который применялся нами для идентификации сущностей: выберем все существительные и содержащие их фразы, присутствующие в спецификациях на проект. Выбранное существительное представляет атрибут в том случае, если оно описывает свойство, качество, идентификатор или характеристику некоторой сущности или связи
Самым простой метод выделения атрибутов — после идентификации очередной сущности или связи в некоторой спецификации задать себе следующий вопрос: "Какую информацию требуется хранить о...". Ответ на этот вопрос надо искать в тексте спецификации. В некоторых случаях может оказаться полезным попросить пользователей уточнить их требования.
Этап 1.3.1. Выявление простых и составных атрибутов
Важно отметить, что каждый атрибут может быть либо простым, либо составным. Составные атрибуты представляют собой набор простых атрибутов. Например, атрибут "Адрес" может быть простым и представлять все элементы адреса как единое значение: "115 Dumbarton Road, Partick, Glasgow, Gil 6YG". В другом варианте этот же атрибут может быть представлен как составной, т.е. состоящий из серии простых атрибутов, содержащих различные элементы адреса. В этом случае то же самое значение может быть разделено на такие атрибуты, как "Улица" (115 Dumbarton Road), "Район" (Partick), "Город" (Glasgow) и "Почтовый код" (Gil 6YG). Выбор способа представления адреса в виде простого или составного атрибута определяется требованиями, предъявляемыми к приложению пользователем. Если пользователь не нуждается в доступе к отдельным элементам адреса, то его целесообразно представить как простой атрибут. Но если пользователю потребуется независимый доступ к отдельным элементам адреса, то атрибут "Адрес" следует сделать составным, образованным из необходимого количества простых атрибутов.
На данном этапе важно идентифицировать все простые атрибуты, которые должны быть представлены в концептуальной модели базы данных, включая и те, которые впоследствии будут использованы для создания составных атрибутов.
Этап 1.3.2. Выявление производных атрибутов
Атрибуты, значения которых могут быть установлены с помощью значений других атрибутов, называются производными, или вычисляемыми. Примерами производных атрибутов являются следующие:
• количество работников данного отделения предприятия;
• возраст работника;
• общая сумма зарплаты всего персонала данного отделения предприятия;
• количество объектов недвижимости, которыми занимается персонал данного отделения предприятия.
Очень часто подобные атрибуты вообще не отображаются в концептуальной модели данных. Однако в некоторых случаях может иметь место риск удаления или модификации атрибута или атрибутов, значения которых используются для вычисления значения производного атрибута. В этом случае производный атрибут должен быть представлен в модели данных, что позволит предупредить нежелательную потерю информации. Однако, если производный атрибут показан в модели данных, следует непременно указать, что он является именно производным. При определении используемых в некотором приложении атрибутов очень часто оказывается, что на предыдущих этапах одна или более сущностей были пропущены. В этом случае следует вернуться к уже выполненным этапам и документально оформить вновь обнаруженные сущности, после чего проанализировать связи, в которых они принимают участие.
Может оказаться полезным подготовить список всех атрибутов, используемых в спецификациях на проект. По мере связывания очередного атрибута с некоторой сущностью или связью, он вычеркивается из списка. Подобный метод позволяет гарантировать, что каждый из атрибутов будет связан с сущностью или связью только одного типа. Когда из списка будет вычеркнут последний атрибут, все идентифицированные в модели атрибуты окажутся связанными с некоторой сущностью или связью.
Следует иметь в виду, что в определенных случаях создается впечатление, что некоторые атрибуты должны быть связаны с сущностями нескольких различных типов. Подобная ситуация возникает в следующих случаях.
1. Идентифицированы несколько сущностей (например, "Управляющий", "Инспектор" и "Начальник"), которые, по сути, представляют экземпляры одной и той же обобщенной сущности (например, "Руководитель"). В этом случае следует обдумать, можно ли объединить все эти сущности в единую сущность или стоит сохранить их как независимые сущности, отражающие в приложении различные роли отдельных экземпляров более общей сущности. Вопросы специализации и объединения сущностей будут подробно рассмотрены при обсуждении этапа 1.6.
2. Обнаружена новая связь между сущностями различных типов. В этом случае атрибут следует связать с какой-либо одной сущностью, которая будет называться родительской, после чего выполнить определение связи, как указано в описании этапа 1.2, включая пополнение документации детальными данными о новой связи.
Этап 1.3.3. Документирование атрибутов
Каждому выявленному атрибуту следует присвоить осмысленное имя, понятное пользователям. О каждом атрибуте в документацию помещаются следующие сведения:
• имя атрибута и его описание;
• любые алиасы, или синонимы, имеющиеся для данного атрибута;
• тип данных и размерность значения;
• значение, принимаемое для атрибута по умолчанию (если таковое имеется);
• является ли атрибут обязательным (т.е. может ли он отсутствовать или иметь значение NULL);
• является ли атрибут составным и, если это так, из каких простых атрибутов он состоит;
• является ли данный атрибут производным и, если это так, какой метод следует использовать для вычисления его значения;
• является ли данный атрибут множественным
Этап 1.4. Определение доменов атрибутов
Задача этого этапа построения локальной концептуальной модели данных состоит в определении доменов атрибутов для всех атрибутов, присутствующих в модели. Доменом называется некоторый пул значений, элементы которого выбираются для присвоения значений одному или более атрибутам. Ниже приведено несколько примеров доменов.•
• Домен атрибута, включающий допустимые номера отделений предприятия. Он состоит из трехсимвольных строк, в которых первый символ является буквой, а остальных два — цифрами, задающими числа в диапазоне 1-99
• Домен атрибута, включающий допустимые значения номеров телефонов и факсов. Он состоит из строк длиной в 13 цифровых символов.
• Допустимыми значениями для атрибута "Пол" сущности "Работник" являются "М" и "Ж". Домен этого атрибута состоит из двух строк длиной в один символ, имеющих указанные значения.
Этап 1.4.1. Определение доменов
Полностью разработанная модель данных должна включать домены для каждого из присутствующих в ней атрибутов. Домены должны содержать следующие данные:
• набор допустимых значений для атрибута;
• сведения о размере и формате каждого из полей атрибутов.
Этап 1.4.2. Документирование доменов атрибутов
После определения доменов атрибутов их имена и характеристики помещаются в словарь данных. Одновременно обновляются записи словаря данных, относящиеся к атрибутам, — в них заносятся имена назначенных каждому атрибуту доменов.
Этап 1.5. Определение атрибутов, являющихся потенциальными и первичными ключами
Этап 1.5.1. Определение потенциальных ключей
На этом этапе для каждой сущности устанавливается потенциальный ключ (или ключи), после чего осуществляется выбор первичного ключа. Потенциальным ключом называется атрибут или минимальный набор атрибутов заданной сущности, позволяющий уникальным образом идентифицировать каждый ее экземпляр. Для некоторых сущностей возможно наличие нескольких потенциальных ключей. В этом случае среди них нужно выбрать один ключ, который будет называться первичным ключом. Все остальные потенциальные ключи будут называться альтернативными ключами.
Этап 1.5.2. Выбор первичного ключа
При выборе первичного ключа среди нескольких потенциальных руководствуйтесь приведенными ниже рекомендациями.
• Используйте потенциальный ключ с минимальным набором атрибутов.
• Используйте тот потенциальный ключ, вероятность изменения значений которого минимальна.
• Выбирайте тот потенциальный ключ, который имеет минимальную вероятность потери уникальности значений в будущем.
• Используйте потенциальный ключ, значения которого имеют минимальную длину (в случае текстовых атрибутов).
Остановите свой выбор на потенциальном ключе, с которым будет проще всего работать (с точки зрения пользователя).
Этап 1.5.3. Документирование первичных и альтернативных ключей
После выбора первичных и альтернативных (если они существуют) ключей сущностей сведения о них необходимо поместить в словарь данных.
Этап 1.6. Специализация или генерализация типов сущностей (необязательный этап)
На этом этапе при необходимости можно продолжить разработку ER-модели, используя процедуры специализации или генерализации по отношению к сущностям, выделенным на этапе 1.1. При проведении специализации предпринимается попытка выделить различия — путем определения одного или более подклассов некоторой сущности, которая в этом случае называется суперклассом специализации. При проведении генерализации предпринимается попытка выделить общие свойства некоторых сущностей — путем определения обобщающей сущности, называемой суперклассом генерализации.
Этап 1.7. Создание диаграммы „сущность-связь"
На этом этапе создаются окончательные варианты ER-диаграмм, отображающих локальные концептуальные модели данных, характеризующие представления отдельных пользователей о предметной области приложения.
Этап 1.8. Обсуждение локальных концептуальных моделей данных с конечными пользователями
Прежде чем завершить первый этап разработки, необходимо обсудить созданные локальные концептуальные модели данных с конечными пользователями. Концептуальная модель данных должна быть представлена ER-диаграммой и сопроводительной документацией, содержащей описание разработанной модели данных. Если в предложенной модели будут обнаружены какие-либо несоответствия, следует внести в нее необходимые изменения (скорее всего, для этого потребуется повторно выполнить один или несколько предыдущих этапов разработки). Этот процесс должен продолжаться до тех пор, пока пользователь не подтвердит, что предложенная ему модель адекватно отражает его личное представление о работе приложения и предприятия в целом.
Т.О. Каждая локальная концептуальная модель данных включает следующее:
• типы сущностей;
• типы связей;
• атрибуты;
• домены атрибутов;
• потенциальные ключи;
• первичные ключи.
Концептуальная модель данных дополняется документацией, создаваемой в процессе разработки этой модели.
2. Методы логического проектирования баз данных реляционного типа
Логическое проектирование баз данных - Процесс конструирования общей информационной модели предприятия на основе отдельных моделей данных пользователей, которая является независимой от особенностей реально используемой СУБД и других физических условий.
Отправным пунктом проводимого в этой главе обсуждения является созданный на первом этапе предлагаемой методологии проектирования набор локальных концептуальных моделей данных и соответствующей документации. Отдельные модели данных отражают представления о предметной области приложения различных типов его пользователей.
Этап 2. Построение и проверка локальной логической модели данных для отдельных представлений каждого из типов пользователей
Этап 2.1. Преобразование локальной концептуальной модели данных в локальную логическую модель
В результате выполнения первого этапа мы получим набор локальных концептуальных моделей данных, отражающих представление отдельных пользователей о работе предприятия. Однако эти модели данных могут содержать некоторые структуры данных, реализация которых в обычных типах СУБД будет затруднена. На этом этапе подобные структуры данных преобразуются в такую форму, которая не вызовет затруднений при их реализации в среде существующих СУБД. Может последовать замечание, что эти действия не являются элементом логического проектирования баз данных. Однако предлагаемая процедура заставляет разработчика более тщательно обдумывать смысл каждого элемента данных, что положительно сказывается на точности отображения в модели особенностей того или иного предприятия. На данном этапе выполняются следующие действия.
1. Удаление связей типа M:N.
2. Удаление сложных связей.
3. Удаление рекурсивных связей.
4. Удаление связей с атрибутами.
5. Удаление множественных атрибутов.
6. Перепроверка связей типа 1:1.
7. Удаление избыточных связей.
Этап 2.1.1. Удаление связей типа M:N
Если в концептуальной модели присутствуют связи типа M:N ("многие ко многим"), то их следует устранить путем определения некоторой промежуточной сущности (см. раздел 5.2.1). Связь типа M:N заменяется двумя связями типа 1:М, устанавливаемыми со вновь созданной сущностью.
Этап 2.1.2. Удаление сложных связей
Сложной называется связь, существующая между тремя и больше типами сущностей (см. раздел 5.1.3). Если в концептуальной модели присутствует сложная связь, ее следует устранить с помощью промежуточной сущности. Сложная связь заменяется необходимым количеством бинарных связей типа 1:М, устанавливаемых со вновь созданной сущностью.
Этап 2.1.3. Удаление рекурсивных связей
Рекурсивными называются такие связи, в которых сущность некоторого типа взаимодействует сама с собой (см. раздел 5.1.3). Если концептуальная модель содержит рекурсивные связи, они должны быть устранены посредством определения некоторой промежуточной сущности.
Удаление рекурсивной связи типа M:N выполняется так же, как и бинарных связей типа M:N, описанных выше.
Этап 2.1.4. Удаление связей с атрибутами
Если в концептуальной модели присутствуют связи, имеющие собственные атрибуты, они должны быть преобразованы путем создания новой сущности. Например, рассмотрим ситуацию, когда требуется фиксировать количество рабочих часов, отработанных временным персоналом каждого из отделений предприятия
Этап 2.1.5. Удаление множественных атрибутов
Множественными называют атрибуты, которые могут иметь одновременно несколько значений для одного и того же экземпляра сущности. Если в концептуальной модели присутствует множественный атрибут, его следует преобразовать путем определения новой сущности. Например, для отображения ситуации, когда одно и то же отделение компании имеет несколько телефонных номеров, в концептуальной модели был определен множественный атрибут. Этот множественный атрибут следует удалить, определив новую сущность Telephone, имеющую единственный простой атрибут Tel_No, и создав новую связь типа 1:М с именем.
Этап 2.1.6. Перепроверка связей типа 1:1
В процессе определения сущностей могли быть созданы две различные сущности, которые на самом деле представляют один и тот же объект в предметной области приложения. Например, могли быть созданы две сущности которые на самом деле представляют один и тот же тип объекта. В подобном случае следует объединить эти две сущности в одну. Если первичные ключи объединяемых сущностей различны, выберите один из них в качестве первичного, а другой укажите как альтернативный ключ.
Этап 2.1.7. Удаление избыточных связей
Связь является избыточной, если одна и та же информация может быть получена не только через нее, но и с помощью другой связи. Всегда следует стремиться создавать минимальные модели данных, и поэтому, если избыточная связь не является очевидно необходимой, ее следует удалять. Установить, что между двумя сущностями имеется больше одной связи, довольно просто. Однако из этого еще не следует, что одна из двух связей обязательно является избыточной, поскольку обе они могут представлять различные объединения, реально существующие в организации.
При устранении избыточности доступа большое значение имеют временные показатели. Суть состоит в том, что при устранении избыточности очень важно исследовать значение каждой из связей, существующих между сущностями.
По завершении данного этапа мы получили упрощенную локальную концептуальную модель данных, из которой удалены все структуры, реализация которых в среде реляционных СУБД затруднительна.
Этап 2.2. Определение набора отношений исходя из структуры локальной логической модели данных
На данном этапе нам предстоит на основе созданных локальных логических моделей данных определить наборы отношений, необходимые для представления сущностей и связей, входящих в представления отдельных пользователей о предметной области приложения.
Теперь мы рассмотрим, как отношения, отражающие сущности и связи между ними, могут быть созданы исходя из имеющихся в логической модели различных, допустимых структур данных.
Связи, которые сущность имеет с другими типами сущностей, представляются с помощью механизма первичных и внешних ключей. Для принятия решения о том, откуда взять и куда поместить значения атрибута(ов) внешнего ключа, предварительно следует установить, какая из участвующих в связи сущностей является родительской, а какая — дочерней. Родительской считается сущность, которая передает копию набора значений своего первичного ключа в отношение, представляющее дочернюю сущность, где эти значения будут играть роль внешнего ключа.
Этап 2.2.1.Бинарные связи типа „один к одному" (1:1)
Для каждой присутствующей в логической модели данных бинарной связи типа 1:1, установленной между сущностями Е1 и Е2, мы должны переслать атрибуты первичного ключа сущности Е1 в отношение, представляющее сущность Е2. Эти атрибуты будут использоваться в нем в качестве внешнего ключа. Определение родительской и дочерней сущностей зависит от ограничений участия, наложенных на члены отношения Е1 и Е2. Сущность, которая частично участвует в связи, определяется как родительская, а та сущность, которая участвует в связи полностью (тотально), определяется как дочерняя. Как уже указывалось выше, копия набора значений первичного ключа родительской сущности помещается в отношение, представляющее дочернюю сущность. Отметим, что в том случае, когда оба вида сущностей участвуют в связи типа 1:1 либо тотально, либо частично, выбор родительской и дочерней сущностей может выполняться произвольно. Более того, если обе сущности участвуют в связи тотально, можно (на выбор) либо представить эту связь с помощью пары первичного и внешнего ключей (как описывалось выше), либо слить атрибуты обеих сущностей в единое отношение. Слияние в единое отношение предпочтительнее в том случае, если данные сущности не принимают участия в других типах связей. Ниже приведен пример, иллюстрирующий, как связь типа 1:1 можно представить в отношениях, созданных на базе предложенной выше логической модели данных.
Этап 2.2.2. Бинарные связи типа „один ко многим" (1:М)
Для каждой бинарной связи типа 1:М, установленной в логической модели данных между сущностями Е1 и Е2, необходимо переслать копию атрибутов первичного ключа сущности Е1 в отношение, представляющее сущность Е2, где они будут играть роль внешнего ключа. Сущность, представляющая "единичную" сторону связи определяется как родительская, а сущность, представляющая "множественную" сторону, — как дочерняя. Как и в предыдущем случае, для представления данной связи необходимо скопировать первичный ключ родительской сущности в отношение, представляющее дочернюю сущность, где этот ключ должен быть описан как внешний.
Этап 2.2.3. Связи типа „суперкласс/подкласс"
Для каждой присутствующей в логической модели данных связи типа "суперкласс/подкласс" сущность суперкласса необходимо определить как родительскую, а сущность подкласса — как дочернюю. Существуют различные варианты представления подобных связей в виде одного или нескольких отношений. Выбор наиболее подходящего варианта зависит от ограничений участия и пересечения, наложенных на участников связи типа "суперкласс/подкласс".
Самым целесообразным решением для связи типа "суперкласс/подкласс" с тотальными и непересекающимися членами является представление каждого из подклассов в виде отдельного отношения, содержащего копию первичного ключа суперкласса.
Этап 2.2.4. Документирование созданных отношений и атрибутов внешних ключей
Документирование состава отношений, созданных на базе каждой из логических моделей данных, осуществляется на языке DBDL (Data Base Definition Language). Кроме того, следует обновить содержимое словаря данных для отображения сведений о любых новых ключевых атрибутах, определенных на данном этапе.
Этап 2.3. Проверка модели с помощью правил нормализации
Нормализация используется для улучшения модели данных, для того чтобы она удовлетворяла различным ограничениям, позволяющим исключить нежелательное дублирование данных. Нормализация гарантирует, что полученная в результате ее применения модель данных будет наилучшим образом отображать особенности использования информации на предприятии, не содержать противоречий, иметь минимальную избыточность и максимальную устойчивость.
Нормализация представляет собой процедуру принятия решений о том, какие именно атрибуты должны быть объединены для представления сущностей каждого типа. В одной из фундаментальных концепций теории нормализации утверждается, что атрибуты должны быть сгруппированы в отношения в соответствии с существующими между ними логическими связями. В некоторых случаях имеют место утверждения, что нормализация разрабатываемых баз данных не позволяет достичь максимальной производительности при их обработке. На это можно ответить следующими замечаниями.
Нормализация проекта позволяет организовать размещение данных в соответствии с их функциональными зависимостями. Поэтому данная процедура должна выполняться между этапами концептуального и физического проектирования.
На предыдущем этапе был создан набор отношений, реализующих локальные логические модели данных. На этом этапе мы проанализируем корректность объединения атрибутов в каждом из отношений. Другими словами, наша задача состоит в проверке корректности состава каждого из созданных отношений посредством применения к ним процедуры нормализации. Процесс нормализации включает следующих четыре основных этапа:
• приведение к первой нормальной форме (1НФ), позволяющее удалить из отношений повторяющиеся группы атрибутов;
• приведение ко второй нормальной форме (2НФ), позволяющее устранить частичную зависимость атрибутов от первичного ключа;
• приведение к третьей нормальной форме (ЗНФ), позволяющее устранить транзитивную зависимость атрибутов от первичного ключа;
• приведение к нормальной форме Бойса-Кодда (НФБК), позволяющее удалить из функциональных зависимостей оставшиеся аномалии.
Целью выполнения этих этапов является получение гарантий того, что каждое из отношений, созданных на основании логической модели данных, отвечает, по крайней мере, требованиям НФБК. Если будут найдены отношения, не отвечающие требованиям НФБК, это может указывать на то, что часть логической модели данных неверна. либо преобразование логической модели в набор отношений выполнено некорректно. При необходимости потребуется перестроить модель данных и убедиться, что она верно отображает моделируемую часть информационной структуры предприятия.
Этап 2.4. Проверка модели в отношении транзакций пользователей
Целью выполнения данного этапа является проверка локальной логической модели данных на возможность выполнения всех транзакций, предусмотренных данным представлением пользователя. Транзакция - это неделимая, с точки зрения воздействия на СУБД, последовательность операций манипулирования данными. Для пользователя транзакция выполняется по принципу "все или ничего", т.е. либо транзакция выполняется целиком и переводит базу данных из одного целостного состояния в другое целостное состояние, либо, если по каким-либо причинам, одно из действий транзакции невыполнимо, или произошло какое-либо нарушение работы системы, база данных возвращается в исходное состояние, которое было до начала транзакции (происходит откат транзакции). С этой точки зрения, транзакции важны как в многопользовательских, так и в однопользовательских системах. В однопользовательских системах транзакции - это логические единицы работы, после выполнения которых база данных остается в целостном состоянии. Транзакции также являются единицами восстановления данных после сбоев - восстанавливаясь, система ликвидирует следы транзакций, не успевших успешно завершиться в результате программного или аппаратного сбоя. Эти два свойства транзакций определяют атомарность (неделимость) транзакции. В многопользовательских системах, кроме того, транзакции служат для обеспечения изолированной работы отдельных пользователей - пользователям, одновременно работающим с одной базой данных, кажется, что они работают как бы в однопользовательской системе и не мешают друг другу.
Перечень транзакций определяется в соответствии со спецификациями, описывающими действия, выполняемые данным пользователем. Используя ER-диаграммы, словарь данных и установленные связи между первичными и внешними ключами, указанные в описании отношений, мы попытаемся выполнить все необходимые операции доступа к данным вручную. Если нам удастся подобным образом найти способ выполнения всех требуемых транзакций, то на этом проверка логической модели данных будет завершена. Однако, если какую-либо из транзакций выполнить вручную не удастся, значит, составленная модель данных является неадекватной и содержит ошибки, которые потребуется устранить. Вероятнее всего, ошибка будет связана с пропуском в модели данных сущности, связи или атрибута.
Рассмотрим два возможных подхода, благодаря которым мы сможем убедиться, что локальная логическая модель данных позволяет выполнить все необходимые транзакции. Первый подход предусматривает выполнение проверки того, что данная логическая модель предоставляет всю информацию (сущности, связи и их атрибуты) необходимую для выполнения каждой из транзакций. Практически это реализуется при подготовке описания требований, выдвигаемых каждой из транзакций.
Второй подход к проверке модели данных на соответствие требуемым транзакциям заключается в нанесении непосредственно на ER-диаграммы всех путей, которые потребуются для выполнения каждой из транзакций.
Этот подход позволяет визуально выделить те области модели, которые не используются для выполнения транзакций, а также те области, которые наиболее существенны с точки зрения выполнения транзакций. В нашем распоряжении оказывается удобное средство прямого анализа поддержки, которую модель данных обеспечивает для выполнения необходимых транзакций пользователя. Если на диаграмме имеются области, которые не используются ни в одной из транзакций, возникает вопрос о целесообразности представления этой информации в модели данных. В то же время, роли в модели присутствуют области, которые не позволяют найти подходящий метод выполнения некоторой транзакции, потребуется провести анализ того, какая из обязательных для выполнения транзакции сущностей или связей была пропущена при составлении модели.
Этап 2.5. Создание диаграмм „сущность-связь"
Создание окончательного варианта диаграмм "сущность-связь" (ER-диаграмм), являющихся локальным логическим представлением данных, используемых отдельными пользователями приложения. Данные на этих диаграммах были проверены с применением методов нормализации, а также проконтролированы на предмет возможности выполнения всех требуемых транзакций.
Этап 2.6. Определение требований поддержки целостности данных
Ограничения целостности данных представляют собой такие ограничения, которые вводятся с целью предотвратить помещение в базу противоречивых данных.
Здесь мы обсудим пять типов ограничений целостности данных:
• обязательные данные;
• ограничения для доменов атрибутов;
• целостность сущностей;
• ссылочная целостность;
• требования данного предприятия.
Этап 2.6.1. Обязательные данные
Некоторые атрибуты всегда должны содержать одно из допустимых значений. Другими словами, эти атрибуты не могут иметь пустого значения. Эти ограничения должны фиксироваться при занесении сведений об атрибуте в словарь данных .
Этап 2.6.2. Ограничения для доменов атрибутов
Каждый атрибут имеет домен, представляющий собой набор его допустимых значений. Например, атрибут "пол" может содержать одно из двух допустимых значений — "М" или "Ж", поэтому его домен состоит из двух символьных строк длиной в один символ, содержащих указанные значения. Данные ограничения устанавливаются при определении доменов атрибутов, присутствующих в модели данных.
Этап 2.6.3. Целостность сущностей
Первичный ключ любой сущности не может содержать пустого значения. Подобные ограничения должны учитываться при определении первичных ключей для сущностей каждого типа.
Этап 2.6.4. Ссылочная целостность
Внешний ключ связывает каждую строку дочернего отношения с той строкой poдительского отношения, которая содержит это же значение соответствующего потенциального ключа. Понятие ссылочной целостности означает, что если внешний ключ содержит некоторое значение, то оно обязательно должно присутствовать в потенциальном ключе одной из строк родительского отношения.
Следующая проблема связана с организацией поддержки ссылочной целостности. Реализация этой поддержки осуществляется посредством задания ограничений существования, определяющих условия, при которых может вставляться, обновляться или удаляться каждое значение потенциального или внешнего ключа. Рассмотрим следующие ситуации.
Случай 1. Вставка новой строки в дочернее отношение. Для обеспечения ссылочной целостности необходимо убедиться, что значение атрибута внешнего ключа новой строки равно пустому значению либо некоторому конкретному значению, присутствующему в одной из строк отношения.
Случай 2. Удаление строки из дочернего отношения. При удалении строки из дочернего отношения никаких нарушений ссылочной целостности не происходит.
Случай 3. Обновление внешнего ключа в строке дочернего отношения (Property). Этот случай подобен случаю 1. Для сохранения ссылочной целостности необходимо убедиться, что атрибут в обновленной строке отношения содержит либо пустое значение, либо некоторое конкретное значение, присутствующее в одной из строк отношения.
Случай 4. Вставка строки в родительское отношение (Staff). Вставка строки в родительское отношение (Staff) не может вызвать нарушения ссылочной целостности. Добавленная строка просто становится родительским объектом, не имеющим дочерних объектов. В данном случае это означает, что новый работник еще не отвечает ни за какие объекты недвижимости
Случай 5. Удаление строки из родительского отношения (Staff). При удалении строки из родительского отношения ссылочная целостность будет нарушена в том случае, если в дочернем отношении будут существовать строки, ссылающиеся на удаленную строку родительского отношения. Другими словами, ссылочная целостность будет нарушена, если удаленный работник отвечал за один или больше объектов недвижимости. В этом случае может быть использована одна из следующих стратегий.
NO ACTION. Удаление строки из родительского отношения запрещается, если в дочернем отношении существует хотя бы одна ссылающаяся на нее строка. В нашем случае это звучит так: "Нельзя удалить сведения о работнике, отвечающем в настоящий момент хотя бы за один объект недвижимости".
CASCADE. При удалении строки из родительского отношения автоматически удаляются все ссылающиеся на нее строки дочернего отношения. Если любая из удаляемых строк дочернего отношения выступает в качестве родительской стороны в некоторой другой связи, то операция удаления применяется ко всем строкам дочернего отношения этой связи и т.д. Другими словами, удаление строки родительского отношения автоматически распространяется на любые дочерние отношения. В нашем случае это звучит так: "Удаление работника автоматически влечет за собой удаление сведений обо всех объектах недвижимости, которыми он занимался".
SET NOLL. При удалении строки из родительского отношения во всех ссылающихся на нее строках дочернего отношения в атрибут внешнего ключа записывается пустое значение. Следовательно, удаление строк из родительского отношения вызовет занесение пустого значения в соответствующий атрибут строк дочернего отношения. В нашем случае это звучит так: "При удалении работника все объекты недвижимости, которыми он занимался, остаются без отвечающего за них работника". Эта стратегия может использоваться только в тех случаях, когда в атрибут внешнего ключа дочернего отношения разрешается помещать пустые значения.
SET DEFAULT. При удалении строки из родительского отношения в атрибут внешнего ключа всех ссылающихся на нее строк дочернего отношения автоматически помещается значение, указанное для этого атрибута как значение по умолчанию. Таким образом, удаление строки из родительского отношения вызывает помещение принимаемого по умолчанию значения в атрибут внешнего ключа всех строк дочернего отношения, ссылающихся на удаленную строку. В нашем случае это будет звучать так: "При удалении работника все объекты недвижимости, которыми он занимался, передаются некоторому другому работнику (например, руководителю отделения)". Эта стратегия применима только в тех случаях, когда атрибуту внешнего ключа дочернего отношения назначено некоторое значение, принимаемое по умолчанию.
NO CHECK. При удалении строки из родительского отношения никаких действий по сохранению ссылочной целостности данных не предпринимается.
Случай 6. Обновление первичного ключа в строке родительского отношения (Staff). Если значение первичного ключа некоторой строки родительского отношения будет обновлено, нарушение ссылочной целостности будет иметь место в том случае, если в дочернем отношении существуют строки, ссылающиеся на исходное значение первичного ключа. В нашем случае это значит, что работник, для которого было выполнено обновление, в данный момент отвечал за один или более объектов недвижимости. Для сохранения ссылочной целостности может использоваться любая из описанных выше стратегий. При использовании стратегии CASCADE обновление значения первичного ключа в строке родительского отношения будет отображено в любой строке дочернего отношения, ссылающейся на данную строку (каскадным образом).
Этап 2.6.5. Требования данного предприятия
В заключение требуется проанализировать ограничения, называемые ограничениями предприятия (или бизнес-правилами). Например, обновление сущностей может регламентироваться принятыми на предприятии правилами, описывающими методы выполнения транзакций, связанных с подобными обновлениями. В компании может быть принято правило, запрещающее одному работнику одновременно заниматься более чем десятью объектами недвижимости.
Этап 2.6.6. Документирование всех ограничений целостности данных
Поместите сведения обо всех установленных ограничениях целостности данных в словарь данных. Они потребуются на этапе физической реализации базы данных.
Этап 2.7. Обсуждение разработанных локальных логических моделей данных с конечными пользователями
На данный момент работа над локальными моделями данных, отражающих представления конкретных пользователей о работе предприятия, должна быть закончена и полностью отражена в документации. Однако прежде чем второй этап разработки можно будет считать полностью завершенным, необходимо обсудить с пользователями созданные логические модели данных и всю сопроводительную документацию.
Этап 3. Создание и проверка глобальной логической модели данных
На данном этапе фазы логического проектирования баз данных строится глобальная логическая модель данных, создаваемая посредством слияния отдельных логических моделей данных, отражающих представления каждого пользователя. По завершении объединения локальных моделей необходимо проверить правильность полученной глобальной модели, как в отношении правил нормализации, так и в отношении возможности выполнения транзакций, предусмотренных спецификациями на функции отдельных пользователей. Проверка выполняется с использованием тех же методов, которые применялись при выполнении этапов 2.3 и 2.4. Однако проведение нормализации потребуется только в том случае, если в процессе слияния были внесены изменения в состав отдельных типов сущностей. Аналогично, проверка возможности выполнения транзакций выполняется только для тех областей модели, которые были подвергнуты изменениям в ходе слияния. В больших системах подобный подход позволяет существенно сократить объем требуемых повторных проверок.
Хотя каждая отдельная логическая модель данных предполагается корректной, "полной и непротиворечивой, любая из них отражает лишь восприятие системы отдельным пользователем или группой пользователей. Другими словами, каждая модель отражает не функции предприятия, а лишь представление о функциях предприятия отдельных его работников. Поэтому любая из этих моделей является неполной. А это означает, что между отдельными моделями в полном наборе представлений могут существовать несовместимость и взаимное перекрытие. Следовательно, при слиянии локальных моделей данных в единую глобальную модель придется прилагать усилия для устранения конфликтов между отдельными представлениями и принимать во внимание их возможное перекрытие.
Этап 3.1. Слияние локальных логических моделей данных в единую глобальную модель данных
В небольших системах, насчитывающих два-три пользовательских представления с незначительным количеством типов сущностей и связей, задача сравнения локальных моделей с последующим слиянием и устранением любых возможных противоречий является относительно несложной. Однако в крупных системах потребуется использовать более систематический подход. Предлагаемый подход предусматривает выполнение следующих действий.
1. Анализ имен сущностей и их первичных ключей.
2. Анализ имен связей.
3. Слияние общих сущностей из отдельных локальных моделей.
4. Включение (без слияния) сущностей, уникальных для каждого локального представления.
5. Слияние общих связей из отдельных локальных моделей.
6. Включение (без слияния) связей, уникальных для каждого локального представления.
7. Проверка на наличие пропущенных сущностей и связей.
8. Проверка корректности внешних ключей.
9. Проверка соблюдения ограничений целостности.
10. Выполнение чертежа глобальной логической модели данных.
11. Обновление документации.
Вероятно, самый простой метод слияния нескольких локальных моделей данных в единую модель состоит в слиянии двух локальных моделей в одну общую модель, с последующим добавлением к ней третьей локальной модели (и т.д.). Процесс добавления к предыдущему результату очередной локальной модели будет продолжаться то тех пор, пока все модели не будут слиты в единую глобальную модель. Этот подход можно считать более простым, чем попытка слить все локальные модели за одну операцию.
Этап 3.1.1.Анализ имен сущностей и их первичных ключей
Может оказаться полезным предварительно проанализировать имена сущностей, присутствующих в локальных моделях данных, — эти сведения можно найти в словаре данных. Проблемы имеют место в следующих случаях:
• если две или более сущностей имеют одно и то же имя, но на самом деле отличаются одна от другой;
• если две или более сущностей идентичны, но имеют различные имена.
Для выявления возможных проблем следует сравнить между собой составы данных сущностей каждого типа. В частности, обнаружить эквивалентные сущности с различными именами поможет сравнение их первичных ключей.
Этап 3.1.2. Анализ имен связей
Выполняемые действия аналогичны описанным на предыдущем этапе.
Этап 3.1.3. Слияние общих сущностей из отдельных локальных моделей
Теперь следует проанализировать имена и содержимое сущностей каждого типа, присутствующих в сливаемых логических моделях. Обычно эта процедура включает следующие действия:
• слияние сущностей с одинаковыми именами и первичными ключами;
• слияние сущностей с одинаковыми именами, но с различными первичными ключами;
• слияние сущностей с различными именами, имеющих одинаковые или различные первичные ключи.
Слияние сущностей с одинаковыми именами и первичными ключами. Как правило, сущности с одним и тем же первичным ключом представляют один и тот же объект реального мира и, следовательно, должны быть слиты. Объединенная сущность будет включать все атрибуты сливаемых сущностей, за исключением дублирующихся.
Слияние сущностей с одинаковыми именами, но с различными первичными ключами. В некоторых ситуациях могут быть обнаружены две сущности с одним и тем же именем, в которых используются различные первичные ключи, однако имеются одинаковые потенциальные ключи. В этом случае сущности сливаются аналогично тому, как это было сделано в предыдущем варианте. Дополнительно потребуется выбрать в результирующей сущности первичный ключ, объявив все остальные ключи альтернативными.
Слияние сущностей с различными именами, имеющих одинаковые или различные первичные ключи. В некоторых случаях можно обнаружить сущности, которые имеют различные имена, но предназначены для одной и той же цели. Подобные эквивалентные сущности можно распознать по их именам, которые будут указывать на их сходное назначение, по их содержанию и по их первичным ключам. Кроме того, их можно распознать по участию в определенных связях. Типичным примером подобной ситуации является наличие в моделях сущностей с названиями Staff (Персонал) и Employee (Работник), которые, по сути, являются эквивалентными и должны быть слиты в единую сущность.
Этап 3.1.4. Включение (без слияния) сущностей, уникальных для каждого
локального представления
На предыдущем этапе были выделены все сущности, описывающие подобные объекты. Все остальные сущности просто включаются в глобальную модель без внесения каких-либо изменений.
Этап 3.1.5. Слияние общих связей из отдельных локальных моделей
На этом этапе анализируются имена и назначение каждой из связей во всех представлениях отдельных пользователей. Прежде чем объединять связи, очень важно разрешить любые конфликты, которые могут иметь место между ними, — например, в отношении ограничений участия или кардинальности. Выполняемые на этом этапе действия включают слияние связей с одинаковыми именами и назначением, после чего может потребоваться выполнить слияние связей с различными именами, но имеющих одно и то же назначение.
Этап 3.1.6. Включение (без слияния) связей, уникальных для каждого локального представления
На предыдущем этапе были выявлены и слиты все связи, имевшие сходное назначение (по определению, эти связи должны существовать между одними и теми же сущностями, которые также должны быть слиты друг с другом). Все оставшиеся связи включаются в глобальную модель без каких-либо изменений.
Этап 3.1.7. Проверка на наличие пропущенных сущностей и связей
Вероятно, одной из самых трудных задач при создании глобальной модели данных является задача выявления пропущенных сущностей и связей между элементами представлений различных пользователей. Если на предприятии существует корпоративная модель данных, она может использоваться для обнаружения сущностей и связей между элементами представлений различных пользователей, которых нет ни в одном из локальных представлений. В то же время, при проведении опросов пользователей конкретного представления в качестве превентивной меры следует попросить их уделить некоторое внимание сущностям и связям, которые, по их мнению, могут существовать в других представлениях. Кроме того, при анализе атрибутов сущностей каждого типа можно попробовать выделить ссылки на сущности, принадлежащие другим пользовательским представлениям. Достаточно часто оказывается, что атрибут, связанный с той или иной сущностью в представлении одного пользователя, соответствует первичному ключу, альтернативному ключу или даже простому, неключевому атрибуту некоторой сущности из другого представления.
Этап 3.1.8. Проверка корректности внешних ключей
На этом этапе может осуществляться слияние различных сущностей и связей, изменение первичных ключей и установка новых связей. Убедитесь, что внешние ключи в дочерних сущностях по-прежнему являются корректными, и в случае необходимости внесите в модель все требуемые изменения.
Этап 3.1.9. Проверка соблюдения ограничений целостности
Убедитесь, что установленные для глобальной логической модели ограничения целостности данных не вступают в противоречие с теми ограничениями, которые были установлены для каждого из пользовательских представлений. Любые конфликты следует устранять посредством проведения консультаций с пользователями.
Этап 3.1.10. Выполнение чертежа глобальной логической модели данных
На этом этапе рисуется окончательный вариант ER-диаграммы, представляющей глобальную логическую модель данных, полученную в результате слияния всех локальных моделей.
Этап 3.1.11. Обновление документации
Обновление документации выполняется с целью отображения любых изменений, вносимых в процессе создания глобальной логической модели данных из набора отдельных пользовательских представлений. Очень важно, чтобы документация всегда поддерживалась в актуальном состоянии и точно отражала текущее состояние модели данных. Если впоследствии в модель будут вноситься изменения, либо в ходе физической реализации базы данных, либо в процессе ее сопровождения, все внесенные изменения также должны немедленно фиксироваться в документации. Устаревшая документация часто является источником множества досадных ошибок и служит причиной принятия неверных решений.
Этап 3.2. Проверка глобальной логической модели данных
На этом этапе производятся действия, аналогичные тем, которые выполнялись на этапах 2.3 и 2.4 при проверке каждой из локальных логических моделей данных.
Этап 3.3. Проверка возможностей расширения модели в будущем
Очень важно, чтобы созданная глобальная модель была легко расширяема. Если модель сможет поддерживать только текущие требования, то время ее существования будет весьма ограниченным, а для реализации поддержки новых или изменяющихся требований потребуется прилагать значительные усилия. Необходимо так построить модель, чтобы она была легко расширяема и позволяла реализовать поддержку новых требований с минимальным изменениями в работе уже существующих пользователей.
Следовательно, имеет смысл выполнить проверку созданной модели с точки зрения эффективности реализации новых требований, которые могут иметь место в будущем. Однако не следует вносить в модель каких-либо изменений, пока они не будут одобрены пользователями.
Этап 3.4. Создание окончательного варианта диаграммы „сущность-связь"
Завершив все проверки созданной глобальной логической модели, можно приступить к подготовке окончательного варианта ER-диаграммы. Эта диаграмма должна представлять глобальную логическую модель данных той части предприятия, которая моделируется в данном приложении. Описывающая эту модель документация (включая схему отношений и словарь данных) должна быть обновлена и подготовлена в полном объеме.
Этап 3.5. Обсуждение глобальной логической модели данных с пользователями
Глобальная логическая модель данных предприятия к этому моменту должна быть полностью завершена и проверена. Сама модель и прилагаемая к ней документация предоставляются для просмотра и анализа конечным пользователям, которые должны убедиться, что она точно отображает структуру и функционирование предприятия.
Приложение 4
Средство автоматизированного проектирования баз данных ERwin
1. Общие сведения
ERwin - CASE-средство проектирования баз данных фирмы Platinum. ERwin сочетает графический интерфейс Windows, инструменты для построения ER-диаграмм, редакторы для создания логического и физического описания модели данных и прозрачную поддержку ведущих реляционных СУБД.
ERwin не привязан к технологии какой-либо конкретной фирмы, поставляющей СУБД или средства разработки. Он поддерживает различные серверы баз данных и настольные СУБД, а также может обращаться к базе данных через интерфейс ОDВС. В ERwin встроена поддержка 23 СУБД, среди которых: Oracle; Microsoft SQL Server и т.п., но речь идет только о реляционных СУБД.
ERwin можно использовать совместно с некоторыми популярными средствами разработки клиентских частей приложений: PowerBuilder, Visual Basic, Delphi. Кроме того, ERwin поддерживает работу в среде групповой разработки ModelMart, являющейся продуктом той же Platinum.
Процесс моделирования в ERwin базируется на методологии проектирования реляционных баз данных IDEF1X..
2. Структура процесса моделирования в ERwin
В ERwin используются два уровня представления модели данных: логический и физический (что соответствует концептуальному и логическому уровню, принятым в теории БД). На логическом уровне не рассматривается использование конкретной СУБД, не определяются типы данных (например, целое или вещественное число) и не определяются индексы для таблиц. Целевая СУБД, имена объектов и типы данных, индексы составляют второй (физический) уровень модели ERwin.
ERwin предоставляет возможности создавать и управлять этими двумя различными уровнями представления одной диаграммы (модели), равно как и иметь много вариантов отображения на каждом уровне.
Процесс построения информационной модели состоит из следующих этапов:
1. создание логической модели данных:
• определение сущностей;
• определение зависимостей между сущностями;
• задание первичных и альтернативных ключей;
• определение неключевых атрибутов сущностей;
2. переход к физическому описанию модели:
• назначение соответствий имя сущности - имя таблицы, атрибут
сущности - атрибут таблицы;
• задание триггеров, хранимых процедур и ограничений;
3. генерация базы данных.
3. Создание модели в ERwin
ERwin имеет развитый инструмент для облегчения проектирования модели данных. Интерфейс выполнен в стиле Windows-приложений, достаточно прост и интуитивно понятен.
Кнопки панели инструментов описаны в табл. П.4.1.
Таблица П.4.1.
Кнопки панели инструментов
Создание, открытие, сохранение и печать модели.
Вызов диалога Report Browser для генерации отчетов.
Изменение уровня просмотра модели: уровень сущностей, уровень атрибутов и уровень определений.
Изменение масштаба просмотра модели.
Генерация схемы БД, выравнивание схемы с моделью и выбор сервера (доступны только на уровне физической модели)
Вызов дополнительной панели инструментов для работы с репозиторием Model Mart. (Работа с Model Mart будет рассмотрена в следующем разделе).
Переключение между областями модели – Subject Area.
Для создания моделей данных в ERwin можно использовать две нотации: IDEF1X и IE (Information Engineering). В примерах будет использоваться нотация IDEF1X.
Для внесения сущности в модель необходимо (убедившись предварительно, что Вы находитесь на уровне логической модели – переключателем между логической и физической моделью служит раскрывающийся список в правой части панели инструментов) кликнуть по кнопке сущности на панели инструментов (ERwin Toolbox) , затем кликнуть по тому месту на диаграмме, где Вы хотите расположить новую сущность. Кликнув правой кнопкой мыши по сущности и выбрав из всплывающего меню пункт Entity Editor… можно вызвать диалог Entity Editor, в котором определяются имя, описание и комментарии сущности.
Рис.П.4.1. Диалог Entity Editor
Каждая сущность должна быть полностью определена с помощью текстового описания в закладке Definition. Закладки Note, Note2, Note3, UDP (User Defined Properties - Свойства, Определенные Пользователем) служат для внесения дополнительных комментариев и определений сущности. В закладке Icon каждой сущности можно поставить в соответствие изображение (файл bmp), которое будет отображаться в режиме просмотра модели на уровне иконок.
Каждый атрибут хранит информацию об определенном свойстве сущности. Каждый экземпляр сущности должен быть уникальным. Атрибут или группа атрибутов, которые идентифицируют сущность, называется первичным ключом. Для описания атрибутов следует, кликнув правой кнопкой по сущности, выбрать в появившемся меню пункт Attribute Editor. Появляется диалог Attribute Editor.
Рис.П.4.2. Диалог Attribute Editor
Кликнув по кнопке New…, в появившемся диалоге New Attribute следует указать имя атрибута, имя соответствующей ему колонки и домен. Домен атрибута будет использоваться при определении типа колонки на уровне физической модели. Для атрибутов первичного ключа в закладке Key Group диалога Attribute Editor необходимо сделать пометку в окне выбора Primary Key. При определении первичного ключа может быть рассмотрено несколько наборов атрибутов. Такие наборы называются потенциальными ключами. Например, если рассматривается сущность “Сотрудник”, такими наборами могут быть:
• Имя, Фамилия, Отчество, Дата рождения;
• Номер паспорта;
• Табельный номер;
• Отдел.
К первичным ключам предъявляются определенные требования. Первичный ключ должен однозначно идентифицировать экземпляр сущности (этому требованию не удовлетворяет четвертый ключ, поскольку он может идентифицировать группу сотрудников, работающих в определенном отделе, но не каждого сотрудника). Первичный ключ должен быть компактен, то есть удаление любого атрибута из состава первичного ключа должно приводить к потере уникальности экземпляра сущности (если удалить Дату рождения из первого ключа, то невозможно будет идентифицировать полных тезок). Каждый атрибут из состава первичного ключа не должен принимать NULL – значений (например, если принять в качестве первичного ключа номер паспорта, необходимо быть уверенным, что все сотрудники имеют паспорта). Каждый атрибут первичного ключа не должен менять свое значение в течение всего времени существования экземпляра сущности (сотрудник может сменить фамилию и паспорт, поэтому первый и второй потенциальные ключи не могут стать первичными). Потенциальные ключи, не ставшие первичными, называются альтернативными. Атрибуты, или наборы атрибутов, использующиеся для доступа к группе экземпляров сущности, называются инверсионными ключами. Для описания альтернативных и инверсионных ключей необходимо кликнуть по кнопке … (диалог Attribute Editor, закладка Key Group) и в появившемся диалоге закладка Key Group Editor создать новую ключевую группу (либо инверсионную, либо альтернативную) и указать, какие атрибуты входят в ту или иную группу.
Рис. П.4.3. Диалог Key Group Editor
ERwin имеет несколько уровней отображения диаграммы. Переключиться между ними можно кликнув по любому месту диаграммы, не занятому объектами модели и выбрав в появившемся меню пункт Display Level. В табл. 3 показаны уровни отображения модели.
На уровне атрибутов атрибуты альтернативного ключа помечаются номером (AKm.n), где m – номер ключа, n – номер атрибута в ключе. Инверсионные ключи помечаются номером (IEm.n). В дальнейшем при генерации БД на атрибутах альтернативных ключей могут быть сгенерированы уникальные индексы, на атрибутах инверсионного ключа – неуникальные. Имена индексов задаются в диалоге New Key Group (рис.П.4.3). Атрибуты первичного ключа отображаются выше горизонтальной линии – прочие атрибуты – ниже.
Для установки связи между сущностями нужно воспользоваться кнопками в палитре инструментов.
Рис.П.4.4. Иллюстрация второй нормальной формы
На логическом уровне можно установить идентифицирующую связь один ко многим, связь многие ко многим и неидентифицирующую связь один ко многим (соответственно кнопки – слева направо в палитре инструментов).
Идентифицирующая связь устанавливается между независимой (родительский конец связи) и зависимой (дочерний конец связи) сущностями. Зависимая сущность изображается прямоугольником со скругленными углами (сущность “Служащий”, справа на рис.П.4.4). Экземпляр зависимой сущности определяется только через отношение к родительской сущности, то есть в структуре на рис.4 информация о служащем не может быть внесена и не имеет смысла без информации об отделе, в котором он работает. При установлении идентифицирующей связи атрибуты первичного ключа родительской сущности переносятся в состав первичного ключа дочерней сущности (миграция атрибутов). В дочерней сущности они помечаются как внешний ключ - (FK). При установлении неидентифицирующей связи дочерняя сущность остается независимой, а атрибуты первичного ключа родительской сущности мигрируют в состав неключевых компонентов родительской сущности.
Для редактирования свойств связи следует кликнуть правой кнопкой мыши по связи и выбрать на контекстном меню пункт Relationship Editor. В появившемся диалоге можно задать:
Рис. П.4.5. Диалог Relationship Editor
Мощность (cardinality) связи - служит для обозначения отношения числа экземпляров родительской сущности к числу экземпляров дочерней.
Verb Phrase – фраза, характеризующая отношение между родительской и дочерней сущностями.
Тип связи (идентифицирующая / не идентифицирующая).
Описание связи.
Правила ссылочной целостности (будут сгенерированы при генерации схемы БД).
Имя роли. Имя роли – это синоним атрибута внешнего ключа, которое необходимо, например, при циклической связи. В этом случае нельзя иметь два атрибута с одинаковым именем внутри одной сущности. При задании имени роли атрибут мигрирует в качестве внешнего ключа в состав неключевых атрибутов с именем роли.
Приложение 5
Система управления базами данных Microsoft Visual FoxPro 6.0. РАБОТА с БД
1. Общие сведения
Система Microsoft Visual FoxPro 6.0 содержит все необходимые средства для создания и управления высокопроизводительными 32-х разрядными приложениями и компонентами баз данных. Надежные инструментальные средства и объектно-ориентированный язык, специализированный для работы с данными, идеально подходят для создания современных масштабируемых многоуровневых приложений, интегрируемых в архитектуру клиент/сервер и Интернет
2. Работа с таблицами
2.1. Создание таблиц
Visual FoxPro, как и любая другая реляционная СУБД, хранит данные в таблицах. Таблицы можно создать двумя способами: через меню среды и через командное окно (рис.П.5.1).
2.1.1. Создание таблиц через меню
Если таблица создается через меню, то следует выбрать пункт меню File→New, в открывшемся диалоговом окне New (рис.П.5.2) выбрать переключатель Table для создания таблицы и нажать кнопку New File.
Рис.П.5.1. Главное окно Visual FoxPro
Рис.П.5.2. Создание нового объекта в Visual FoxPro
При выборе мастера (нажатии кнопки Wizard в диалоговом окне New, см. рис.П.5.2) предлагается диалог, с помощью которого можно создать таблицы по имеющимся в FoxPro образцам таблиц (Accounts, Customers и т.д.).
Рассмотрим создание таблицы без применения мастера создания таблиц. После нажатия кнопки New File (см. рис.П.5.2) требуется задать имя создаваемой таблицы, после чего открывается окно конструктора таблиц Table Designer (рис.П.5.3).
Рис.П.5.3. Окно конструктора таблиц. Вкладка Fields
Окно конструктора таблиц содержит три вкладки: Fields – для определения полей таблицы, Indexes – для определения индексов и Table – информационная вкладка.
На вкладке Fields конструктора таблиц необходимо ввести названия полей (атрибутов) таблицы в столбце Name, задать тип данных для каждого поля в столбце Type (по умолчанию стоит тип данных Character), длину поля в столбцы Width и Decimal (Width – общее число символов, Decimal – число символов после запятой, опция Decimal доступна только для полей типа Numeric). Столбец Index задает индекс (ascending – индекс по возрастанию, descending – индекс по убыванию), он автоматически сохраняется с типом Regular и с именем поля, по которому создан индекс (см. п.4) и отражается на вкладке Indexes. Если индекс не определен, то Visual FoxPro при помощи данной опции автоматически создает его. Столбец Null предназначен для указания, допускается ли пустое значение в данном поле. Маленькие кнопки, расположенные слева от имен полей (), служат для изменения порядка отображения полей при просмотре таблицы.
На вкладке Indexes конструктора таблиц (рис.П.5.4) отображаются все индексы, созданные по данной таблице.
Рис.П.5.4. Окно конструктора таблиц. Вкладка Indexes
В столбце Order вкладки Indexes конструктора таблиц отображается порядок индекса (ascending – возрастающий, descending – убывающий), в столбце Name – имя индекса, в столбце Type – тип индекса, в столбце Expression – поле или поля, по которым строится индекс.
На вкладке Table конструктора таблиц (рис.П.5.5) отображается описание таблицы, т.е. адрес, по которому она сохранена (Table file), количество записей (Records), количество полей (Fields), размер записи в таблице (Length).
Назначение кнопок в конструкторе таблиц следующее :
OK – сохраняет структуру таблицы;
Cancel – отменяет проведенные изменения;
Insert – вставляет новое поле (новый атрибут) таблицы;
Delete – удаляет указанное поле (атрибут) таблицы.
Заполнив вкладку Fields, нажимаем кнопку OK, после чего предлагается немедленно начать заполнение таблицы (рис.П.5.6.).
Рис.П.5.5. Окно конструктора таблиц. Вкладка Table
Рис.П.5.6. Запрос на ввод данных
При нажатии кнопки Yes открывается окно для ввода значений атрибутов. По окончании ввода данных закрываем окно ввода (нажав ).
При отказе от немедленного заполнения таблицы (при нажатии кнопки No, см. рис.П.5.6.) можно вернуться к этапу ввода данных позже.
2.1.2. Создание таблиц через командное окно
Командное окно (см. рис.П.5.1) предназначено для ввода команд на языке программирования Visual FoxPro и открывается автоматически при запуске Visual FoxPro или с помощью пункта меню Window→Command Window (или одновременным нажатием клавиш Сntr+F2). Ввод любой команды завершается нажатием клавиши Enter.
Таблицу через командное окно можно создать, выполнив команду Create. Для этого необходимо в командном окне написать команду Create и нажать клавишу Enter. На экране появится диалоговое окно Create (рис.П.5.7.).
.
Рис.П.5.7. Окно Create
В окне Create следует выбрать папку. Если предварительно не была установлена папка по умолчанию (например, с помощью команды SET DEFAULT TO <имя_папки>), открывается папка, в которой установлен пакет Visual FoxPro. В поле Enter table следует указать имя файла таблицы и нажать на кнопку Сохранить. При создании таблицы следует присваивать ей имя, отражающее существо хранимой информации, но в рамках правил операционной системы Windows. После сохранения имени таблицы (рис.П.5.7.) откроется окно Table Designer – конструктор таблиц (см. рис.П.5.3).
Если выполнить команду Create <имя_таблицы>, то таблица c указанным именем сохранится в папку по умолчанию и сразу откроется окно конструктора таблиц Table Designer (см. рис.П.5.3).
2.1.3. Изменение структуры таблиц
Если при вводе данных выявляются ошибки проектирования структуры таблицы, исправить структуру таблицы можно с помощью команды MODIFY STRUCTURE, написанной в командном окне:
select <имя_таблицы> && если таблица открыта
use <имя_таблицы> &&если таблица не открыта
modify structure.
По этой команде откроется окно конструктора таблиц Table Designer (см. рис.П.5.3–П.5.5), в котором можно сделать соответствующие исправления.
2.1.4. Удаление таблиц
Для удаления таблицы необходимо выполнить команду
DROP TABLE <имя_таблицы>.
Еще один способ удаления таблицы – выполнить команду
DELETE FILE <имя_таблицы>.dbf.
В результате выполнения любой из этих команд файл таблицы будет удален с диска.
2.1.5. Использование рабочих областей
Рабочие области используются для одновременной работы с несколькими таблицами. Рабочая область – это виртуальный «рабочий стол», в одной рабочей области может быть открыта только одна таблица. Visul FoxPro имеет 32767 рабочих областей. Открывая таблицы в различных рабочих областях и переключаясь затем между этими рабочими областями (с помощью команды SELECT), можно одновременно работать сразу с несколькими таблицами.
По умолчанию таблица открывается в текущей рабочей области, при этом уже открытая в этой рабочей области таблица закрывается. Например, после последовательного выполнения команд
Use table1
Use table2
Use table3
в результате будет открыта только таблица table3, т.к. при открытии таблицы table2 будет одновременно закрыта таблица table1, а при открытии таблицы table3 будет одновременно закрыта таблица table2.
Для того, чтобы открыть таблицу в рабочей области, отличной от текущей, нужно либо выбрать определенную рабочую область (select <номер рабочей области>), либо выбрать свободную рабочую область с наименьшим номером (select 0). Например, в результате выполнения команд:
Use table1 in 1
Use table2 in 2
Use table3 in 3
будут открыты сразу три таблицы, каждая в своей рабочей области.
Конструкция Use table1 in 1 равносильна выполнению двух команд:
select 1
use table1,
поэтому для открытия трех таблиц в разных рабочих областях можно написать следующие команды:
select 1
Use table1
select 2
Use table2
select 3
Use table3
или
select 0
Use table1
select 0
Use table2
select 0
Use table3
Открытой таблице Visual Fox Pro назначает псевдоним - имя, служащее для ссылок на эту таблицу. По умолчанию псевдоним имеет такое же имя, что и открытая таблица. Для переключения между рабочими областями следует ввести команды:
SELECT <номер_рабочей_области>, если точно известно в какой рабочей области открыта таблица,
SELECT <имя_таблицы>, если псевдоним соответствует имени таблицы (по умолчанию) или
SELECT <псевдоним>, если псевдоним задан и не соответствует названию таблицы, открытой в данной рабочей области.
Команда USE без имени таблицы закрывает таблицу в текущей рабочей области (если рабочая область не указана) или в указанной с помощью команды select рабочей области.
3. Манипулирование данными в таблице
3.1. Ввод данных
Для ввода новой строки (пустой) можно написать в командном окне команду append blank или в окне просмотра содержимого таблицы (с помощью команды BROWSE) нажать сочетание клавиш Cntr+Y. Команда APPEND без аргументов открывает окно, в котором можно вводить данные в таблицу, причем после заполнения строки добавляется новая строка.
3.2. Удаление записей
Для удаления записи (строки) из таблицы необходимо сначала пометить эту запись на удаление, а затем физически удалить командой PACK или через пункт меню Table→Remove Deleted Records.
Чтобы пометить запись на удаление, нужно выполнить одно из следующих действий:
• для текущей записи (строки) нажать сочетание клавиш Cntr+T или выполнить команду delete;
• выполнить команду delete for <условие>, которая помечает на удаление все записи, удовлетворяющие указанному условию,
• щелкнуть левой кнопкой мыши на маркере удаления (крайний левый столбец в окне browse).
Записи, помеченные на удаление, в режиме просмотра содержимого таблицы в зависимости от установок либо не показываются, либо показываются, но помеченные черным перед первым полем записи (на маркере удаления).
Если команда PACK не выполнена, то при нажатии сочетания клавиш Cntr+T в режиме просмотра содержимого таблицы для помеченной на удаление записи пометка на удаление будет отменена. Еще один способ отменить пометку на удаление текущей строки – выполнить команду Recall.
3.3. Редактирование данных
Редактирование отдельных значений полей записи осуществляется при просмотре содержимого таблицы (команда browse).
Если необходимо заменить значение одного атрибута, то можно для текущей строки выполнить команду
REPLACE <имя_атрибута> WITH <новое_значение_атрибута>
или для всех строк, удовлетворяющих заданному условию выполнить команду
REPLACE <имя_атрибута> WITH <новое_значение_атрибута> ;
FOR <условие>.
4. Реструктуризация базы данных
4.1. Создание базы данных
Использование базы данных значительно упрощает работу с данными, т.к. в ней реализованы мощные и полезные функции, используемые при работе с таблицами. Например, в файле с расширением DBF нельзя дать полю имя, содержащее более 10 символов, но если таблица включена в базу данных, то имя поля таблицы может содержать до 128 символов. Никакие правила (RULE), значения по умолчанию (DEFAULT) и триггеры попросту невозможны в файле DBF вне файла базы данных, точнее невозможно их автоматическое выполнение.
Использование файла базы данных позволяет выполнять операции, которые крайне сложно организовать другими способами. Например, такая операция как «транзакция» может быть реализована только среди таблиц, включенных в базу данных. В принципе, этот процесс можно организовать и со свободными таблицами, но это потребует от программиста значительных усилий.
Поэтому в большинстве случаев целесообразно создавать базу данных, включающую и таблицы, и связи между ними.
Базы данных, как и таблицы, можно создать двумя способами: через меню среды Visual FoxPro и через командное окно.
4.1.1. Создание базы данных через меню
Если база данных создается через меню, то следует выбрать пункт меню File→New и в открывшемся диалоговом окне New (см. рис.П.5.2) выбрать переключатель Database и нажать кнопку New File.
На экране появится диалоговое окно Create (аналогично рис.П.5.7.). В нем следует выбрать папку (если предварительно не была установлена папка по умолчанию, например, с помощью команды SET DEFAULT TO <имя_папки>, то открывается папка, в которой установлен пакет Visual FoxPro) и в поле Enter database указать имя файла базы данных. При создании базы данных следует присваивать ей имя, отражающее существо хранимой информации, но в рамках правил операционной системы Windows.
Рис.П.5.8. Набор инструментария Database Controls
Набор инструментария Database Controls, содержит следующие кнопки (слева направо):
New table – создание новой таблицы базы данных;
Add table – добавление в базу данных свободной таблицы;
Remove table – удаление таблицы из базы данных;
New remote view – создание нового удаленного вида;
New local view – создание нового локального вида;
Modify table – изменение структуры таблицы;
Browse table – просмотр содержимого таблицы;
Edit stored procedures – вызов окна редактирования текстов хранимых процедур;
Connections – вызов окна определения соединения.
Чтобы открыть конструктор базы данных для уже созданной базы данных, необходимо выполнить команду
MODIFY DATABASE <имя_базы_данных>.
4.1.2. Создание базы данных через командное окно
Если база данных задается с помощью командного окна (см. рис.П.5.1), то необходимо выполнить команду CREATE DATABASE. На экране появится диалоговое окно Create (аналогично рис.П.5.7.).
При выполнении команды
CREATE DATABASE <имя_базы_данных>
база данных сохранится на диск в текущую папку и сразу будет открыто окно конструктора базы данных.
4.2. Работа с таблицами в базе данных
4.2.1. Добавление таблиц в базу данных
Если таблицы созданы раньше базы данных, то их можно включить в базу данных после ее открытия либо командой add table, либо с помощью мыши в окне конструктора базы данных Database Designer (по нажатию правой кнопки мыши в выпадающем меню выбрать пункт меню Add Table или нажать на кнопку соответствующего инструмента Database Control). В открывшемся окне необходимо выбрать файл таблицы, которую необходимо включить в базу данных.
Если база данных создана раньше, чем таблицы, то создать таблицы в базе данных можно либо с помощью мыши в окне конструктора базы данных Database Designer (по нажатию правой кнопки мыши в выпадающем меню выбрать пункт меню New Table), либо при открытой базе данных создать таблицу.
Изменить структуру базы данных можно с помощью команды MODIFY DATABASE. После ее ввода будет открыто окно конструктора базы данных, в котором можно сделать необходимые изменения.
4.2.2. Редактирование таблиц в базе данных
Редактирование структуры таблиц, включенных в базу данных, осуществляется аналогично редактированию свободных, т.е. не включенных в базу данных таблиц.
Для вызова конструктора таблиц необходимо либо нажать на кнопку соответствующего элемента панели инструментов Database Controls, либо щелкнуть правой кнопкой мыши на таблице внутри конструктора базы данных и выбрать пункт меню Modify.
4.2.3. Удаление таблиц из базы данных
Таблицы можно удалить из базы данных либо через командное окно, либо через меню; причем таблицу можно либо только исключить из базы данных, либо удалить с диска.
Для того чтобы исключить таблицу из базы данных (но не удалить ее с диска) в командном окне необходимо выполнить команду REMOVE TABLE <имя_таблицы>.
Если необходимо не только исключить таблицу из базы данных, но и удалить ее с диска, то необходимо в командном окне выполнить команду
REMOVE TABLE <имя_таблицы> DELETE.
При исключении таблицы из базы данных через меню можно воспользоваться кнопкой исключения таблиц в панели инструментов Database Controls или щелкнуть правой кнопкой мыши на таблице внутри конструктора базы данных и выбрать пункт меню Delete. Visual FoxPro откроет окно, показанное на рис.П.5.9. При нажатии на кнопку Remove таблица будет исключена из базы данных, при нажатии на кнопку Delete – удалена с диска. Кнопка Cancel – отмена операции.
Рис.П.5.9. Подтверждение удаления таблицы
4.3. Связи в базе данных
Структура реляционной базы данных всегда разрабатывается таким образом, чтобы каждая таблица, которая в ней находится, не содержала избыточной информации. Например, в базе данных магазина необходимо хранить данные о товарах, которые продаются в данном магазине. Как следствие, нужно также каким-то образом хранить и названия фирм, которые производит эти товары. Если для этих целей будет использоваться одна таблица, то станет очевидным нерациональное использование памяти компьютера, так как для каждого товара придется хранить в соответствующей записи названия и другие атрибуты фирм, которые будут повторяться много раз. Поэтому необходимо создать две таблицы, которые будут между собой взаимосвязаны. При этом для созданных таблиц необходимо установить связи, чтобы, например, по названию фирмы в таблице фирм определить все записи с товарами этой фирмы из таблицы товаров [5]. Связи бывают «один-к-одному» (1:1), «один-ко-многим» (1:n) и «многие-ко-многим» (m:n) (последние в реляционных СУБД не поддерживаются). Связи между таблицами в базе данных используются при формировании запросов, создании отчетов или разработке форм. Создать связь между таблицами можно только после создания индексов. В родительской таблице должен быть создан индекс типа Primary или Candidate.
Связи могут быть временными (только для текущего сеанса работы с базой данных) и постоянными (сохраняются и остаются на следующий сеанс работы).
4.3.1. Создание связей
Временная связь создается командой Set relation с большим числом дополнительных параметров.
Постоянная связь создается в окне конструктора базы данных. Поля, по которым будут связываться таблицы, должны иметь одинаковый тип данных, но названия их не обязательно должны совпадать. Для создания связи необходимо щелкнуть мышью на имени индекса (первичного ключа) родительской таблицы и, не отпуская клавишу мыши, «перетащить» его к индексу в дочерней таблице.
Линия связи, оканчивающаяся тремя штрихами ( ) показывает, что отношение к данной таблице – «многие». Линия связи, оканчивающаяся одним штрихом ( ) показывает, что отношение к таблице – «один».
4.3.2. Редактирование связей
Для редактирования связи можно выполнить двойной щелчок мышью на линии связи между таблицами и в появившемся меню выбрать пункт меню Edit Relationship. Будет открыто окно редактирования связи, в котором для каждой таблицы в выпадающем списке под ее именем указаны ее индексы, и необходимо выбрать и указать индексы, по которым осуществляется связь.
4.3.3. Удаление связей
Для удаления связи можно выполнить двойной щелчок мышью на линии связи между таблицами и в появившемся меню выбрать опцию Remove Relationship или выделить связь и нажать клавишу Delete.
4.4. Удаление базы данных
Удаление базы данных можно осуществить с помощью команды DELETE DATABASE <имя_базы_данных> DELETETABLES. При выполнении этой команды будет удалена и база данных, и все включенные в нее таблицы.
Команда DELETE DATABASE без фразы DELETETABLES не удаляет одновременно с базой данных все включенные в нее таблицы, а только удаляет в этих таблицах связь с базой данных и оставляет их на диске как свободные таблицы.
5. Работа с индексами
5.1. Создание индексов
Индексы используются для логического упорядочивания записей и организации связей между таблицами, а также для ускорения доступа к данным и для управления порядком отображения записей таблицы.
Под индексным ключом понимается имя поля таблицы или выражение, включающее совокупность имен полей, по которым логически упорядочена таблица.
Индексы бывают простые (состоящие из одного индексного выражения) и составные (состоящие из нескольких индексных выражений). Индексные выражения могут состоять из одного или нескольких полей таблицы.
В Visual FoxPro существует четыре типа индексов (табл.П.5.1.).
Таблица П.5.1. Типы индексов
Тип
Описание
Regular
Значение индексного выражения записывается для каждой строки таблицы. При наличии одного и того же значения для нескольких строк в индексном файле будет указатель на каждую из них. При просмотре таблицы такие строки появляются в порядке их ввода.
Unique
Значение индексного выражения записывается только для первой из повторяющихся строк и только на нее в индексном файле есть указатель. При просмотре таблицы видна только одна (первая) из строк с одинаковым значением индексного выражения.
Candidate
Создается уникальный индекс, не содержащий полей с пустыми значениями. Он является кандидатом на роль первичного ключа, но не является таковым, так как в таблице может быть только один первичный ключ.
Primary
Первичный ключ. В качестве первичного (Primary) ключа может быть выбран один из индексов, удовлетворяющий требованиям индекса типа Candidate,. Используется для связывания таблиц и определения условий целостности данных. Возможен только для таблиц, включенных в базу данных.
Индексы таблиц хранятся в файлах с расширением .CDX (для составных индексов) или .IDX (для простых индексов).
Индексы таблицы можно задать на вкладке Indexes окна конструктора таблиц Table Designer (рис.П.5.4) или с помощью командного окна.
5.1.1. Создание индексов через командное окно
Если индекс создается через командное окно, то необходимо выполнить команды:
select <имя_таблицы> && если таблица открыта
use <имя_таблицы> && если таблица не открыта
index on <имя_поля> to <имя_индекса>;
[ascending/descending] [unique/candidate].
По умолчанию (если не указан тип индекса unique/candidate) создается индекс типа Regular (см. табл.П.5.1.).
Для создания составных индексов используется команда
Index on <имя_поля> tag <имя_индекса>.
В этом случае индексный файл будет иметь расширение .CDX.
Команда Set index to <имя_индекса> открывает один или несколько существующих индексных файлов, используемых с текущей таблицей.
Существует еще один способ создания уникальных и неуникальных индексов.
Команда set unique on/off определяет, поддерживает ли файл индекса записи с повторяющимися значениями ключа индекса.
5.1.2. Создание индексов в конструкторе таблиц
Чтобы создать индексы в конструкторе таблиц, необходимо открыть конструктор таблиц командой Modify Structure и перейти к вкладке Indexes (рис.П.5.10). В столбец Name вводится имя индекса, а из раскрывающегося списка столбца Type выбирается необходимый тип индекса (см. табл.П.5.1.). В столбце Expression вводится выражение, по которому строится индекс (в самом простом случае это имя поля (атрибута) таблицы). Для сохранения изменений необходимо нажать на кнопку ОК.
Рис.П.5.10. Определение индексов в окне конструктора таблиц
5.2. Удаление индексов
Индексы можно удалять с помощью конструктора таблиц или с помощью команд.
Чтобы удалить индексы в конструкторе таблиц, необходимо перейти на вкладку Indexes, указать индекс, подлежащий удалению, и нажать кнопку Delete (см. рис.П.5.10).
Для удаления индекса из составного индекса нужно выполнить команду
Delete Tag <имя_индекса> в командном окне.
5.3. Просмотр результатов индексирования
Чтобы просмотреть результат упорядочивания данных необходимо выполнить следующее.
В случае существующего (уже созданного) индекса: открыть таблицу с существующим индексом командами
Use <имя_таблицы> index <имя_индекса>
или
Use <имя_таблицы>
Set index to <имя_индекса>
Далее просмотреть содержимое таблицы командами browse – для просмотра всех атрибутов или browse fields <список_атрибутов> - для просмотра некоторых атрибутов.
В случае, если индекс еще не создан, то создать индекс, открыть таблицу вместе с данным индексом и просмотреть содержимое таблицы.
Приложение 6
SQL. Язык определения данных
(Data Definition Language — DDL)
1. Запись SQL-операторов
SQL-оператор состоит из зарезервированных слов, а также из слов, определяемых пользователем. Зарезервированные слова являются постоянной частью языка SQL и имеют фиксированное значение. Их следует записывать в точности так, как это установлено, и нельзя разбивать на части для переноса из одной строки в другую. Слова, определяемые пользователем, задаются самим пользователем (в соответствии с определенными синтаксическими правилами) и представляют собой имена различных объектов базы данных — таблиц, столбцов, представлений, индексов и т.д. Слова в операторе размещаются в соответствии с установленными синтаксическими правилами.
Большинство компонентов SQL-операторов не чувствительно к регистру. Это означает, что могут использоваться любые буквы — как строчные, так и прописные. Одним важным исключением из этого правила являются символьные литералы-данные, которые должны вводиться точно так же, как были введены соответствующие им значения, хранящиеся в базе данных. Например, если в базе данных хранится значение фамилии 'SMITH', а в условии поиска указан символьный литерал 'Smith', то эта запись не будет найдена.
Поскольку язык SQL имеет свободный формат, отдельные SQL-операторы и их последовательности будут иметь более читабельный вид при использовании отступов и выравнивания. Рекомендуется придерживаться следующих правил.
• Каждая фраза в операторе должна начинаться с новой строки.
• Начало каждой фразы должно быть выровнено с началом остальных фраз оператора.
• Если фраза имеет несколько частей, каждая из них должна начинаться с новой строки с некоторым отступом относительно начала фразы, что будет указывать на их подчиненность.
Для определения формата SQL-операторов мы будем применять следующую расширенную форму BNF-нотации (Backus Naur Form).
• Прописные буквы будут использоваться для записи зарезервированных слов и должны указываться в операторах точно так же, как это будет показано.
• Строчные буквы будут использоваться для записи слов, определяемых пользователем.
• Вертикальная черта (|) указывает на необходимость выбора одного из нескольких приведенных значений — например, а | b | с.
• Фигурные скобки определяют обязательный элемент - например, {a}.
• Квадратные скобки определяют необязательный элемент – например, [a]
• Многоточие используется для указания необязательных возможности повторения конструкции, от нуля до нескольких раз — например, {a|b} [,с...]. Эта запись означает, что после а или b может следовать от нуля до нескольких повторений с, разделенных запятыми.
Рассмотрим формат и основные возможности важнейших операторов, за исключением специфических операторов, отмеченных в таблице символом «*». Несущественные операнды и элементы синтаксиса (например, принятое во многих системах программирования правило ставить «;» в конце оператора) будем опускать.
2. Описание команд SQL, поддерживаемых СУБД Visual FoxPro
Visual FoxPro поддерживает следующие команды SQL:
ALTER TABLE
Изменение существующей таблицы. Можно изменить имя, тип поля, количество знаков после запятой, диапазон значений, поддержку проверки на NULL, и правила целостности ссылочных данных для каждого поля таблицы.
CREATE CURSOR
Создание временной таблицы. Каждое поле во временной таблице определяется именем, типом, количеством знаков после запятой, поддержку проверки на NULL и правилами целостности ссылочных данных. Эти определения могут быть указаны в командной строке или взяты из массива.
CREATE SQL VIEW
Вызывает окно дизайнера представления (View Designer), который позволяет создавать SQL представление.
CREATE TABLE
Создание таблицы. Каждое поле новой таблицы определяется именем, типом, количеством знаков после запятой, диапазоном значений, поддержкой проверки на NULL и правилами целостности ссылочных данных. Эти определения могут быть указаны в командной строке или взяты из массива.
DELETE
Пометка записей таблицы на удаление
INSERT
Добавление новой записи в конец существующей таблицы. Поля новой записи содержат данные, перечисленные в команде INSERT, или указанные в массиве.
SELECT
Определяет критерии запроса и выполняет запрос. Visual FoxPro интерпретирует запрос и выбирает определенные данные из таблицы. Команда SELECT встроена в Visual FoxPro, как и всякая другая команда Visual FoxPro.
UPDATE
Обновляет записи в таблице. Записи могут быть обновлены согласно результатам предложения SQL SELECT.
3. CREATE TABLE
Типы данных языка SQL, определенные стандартом ISO
В языке SQL существует шесть скалярных типов данных, определенных стандартом ISO.
Тип данных
Объявления
character (Символьный)
CHAR, VARCHAR
bit (Битовый)
BIT, BIT VARYING
exact numeric (Точные числа)
NUMERIC, DECIMAL, INTEGER, SMALLINT
approximate numeric (Округленные числа)
FLOAT, REAL, DOUBLE PRECISION
datetime (Дата/время)
DATE, TIME, TIMESTAMP
interval (Интервал)
INTERVAL
Символьные данные (тип character)
Символьные данные состоят из последовательностей символов, входящих в от деленный создателями СУБД набор символов. Поскольку наборы символов являются специфическими для различных диалектов языка SQL, перечень символов, которые могут входить в состав значений данных символьного типа, также зависит от конкретной реализации. Для определения данных символьного типа используется следующий формат:
CHARACTER [VARYING] [length]
CHARACTER может быть сокращено до CHAR a
CHARACTER VARYING ДО VARCHAR.
При определении столбца с символьным типом данных параметр length использует ся для указания максимального количества символов, которые могут быть помете) данный столбец (по умолчанию принимается значение 1). Символьная строка может быть определена как имеющая фиксированную или переменную (VARYING) длину. Если строка определена с фиксированной длинной значений, то при вводе в нее меньшего количества символов значение дополняется до указанной длины пробелами, добавляемыми справа. Если строка определена с переменной длинной значений, то при вводе в ее меньшего количества символов в базе данных будут сохранены только введенные символы, что позволяет достичь определенной экономии внешней памяти.
Битовые данные (тип bit)
Битовый тип данных используется для определения битовых строк, т.е. последовательности двоичных цифр (битов), каждая из которых может иметь значение либо 0, либо 1. Для определения данных битового типа используется формат, сходный с определением символьных данных:
BIT [VARYING] [length]
Например, для сохранения битовой строки с фиксированной длиной и значением '0011' может быть объявлен столбец bit string: bit_string BIT(4)
Точные числа (тип exact numeric)
Тип точных числовых данных используется для определения чисел, которые имеют точное представление в компьютере. Числа состоят из цифр, необязательной десятичной точки и необязательного символа знака. Данные точного числового типа определяются значностью (precision) и длиной дробной части (scale). Значность задает общее количество значащих десятичных цифр числа, в которое входят длина целой и дробной частей, но без учета самой десятичной точки. Дробная часть указывает количество дробных десятичных разрядов числа. Например, точное число -12.345 имеет значность, равную 5 цифрам, и дробную часть длиной 3. Особой разновидностью точных чисел являются целые числа. Существует несколько способов определения данных точного числового типа:
NUMERIC [ precision [, scale] ]
DECIMAL [ precision [, scale] ]
INTEGER
SMALLINT
INTEGER может быть сокращено до INT a DECIMAL до DEC
Типы NUMERIC и DECIMAL предназначены для хранения чисел в десятичном формате. Но умолчанию длина дробной части равна нулю, а принимаемая по умолчанию значность зависит от реализации. Тип INTEGER используется для хранения больших положительных или отрицательных целых чисел. Тип SMALLINT используется для хранения небольших положительных или отрицательных целых чисел. При использовании этого типа данных расход внешней памяти существенно сокращается. Максимальное абсолютное значение числа, которое может сохраняться в столбцах с типом данных SMALLINT, составляет 32 767
Округленные числа (тип approximate numeric)
Тип округленных чисел используется для описания данных, которые нельзя точно представить в компьютере, — например, действительных чисел. Округленные числа или числа с плавающей точкой представляются в научной нотации, при которой число записывается с помощью мантиссы, умноженной на определенную степень десятки (порядок), например: 10ЕЗ, +5.2Е6, -0.2Е-4. Существует несколько способов определения данных с типом округленных чисел:
FLOAT [precision]
REAL
DOUBLE PRECISION
Параметр precision задает значность мантиссы. Значность определений типа REAL и DOUBLE PRECISION зависит от конкретной реализации.
Дата и время (тип datetime)
Тип данных "дата/время" используется для определения моментов времени с некоторой установленной точностью. Примерами являются даты, отметки времени и время суток. Стандарт ISO разделяет тип данных "дата/время" на подтипы YEAR (Год), MONTH (Месяц), DAY (День), HOUR (Час), MINUTE (Минута), SECOND (Секунда), TIMEZONE_HOUR (Зональный час) и TIMEZONE_MINUTE (Зональная минута). Два последних типа определяют час и минуты сдвига зонального времени по отношению к универсальному координатному времени (Гринвичскому времени). Поддерживается три типа полей даты/времени:
DATE
TIME [time_precision] [WITH TIME ZONE]
TIMESTAMP [time precision] [WITH TIME ZONE]
Тип данных DATE используется для хранения календарных дат, включающих поля YEAR, MONTH и DAY. Тип данных TIME используется для хранения отметок времени, включающих поля HOUR, MINUTE и SECOND. Тип данных TIMESTAMP используется для совместного хранения даты и момента времени. Параметр time_precision задает количество дробных десятичных знаков, определяющих точность сохранения значения в поле SECOND. Если этот параметр опускается, по умолчанию его значение для столбцов типа TIME принимается равным нулю (т.е. сохраняются целые секунды), тогда как для полей типа TIMESTAMP он принимается равным 6 (т.е. отметки времени сохраняются с точностью до миллисекунд). Наличие ключевого слова WITH TIME ZONE определяет использование полей TIMEZONE_HOUR и TIMEZONE_MINUTE. Например, столбец Date таблицы Viewing, представляющий дату (день, месяц и год) осмотра клиентом сдаваемого в аренду объекта, может быть определен следующим образом: date DATE
Данные типа interval
Данные с типом интервала используются для представления периодов времени. Любой интервальный тип данных состоит из набора отдельных полей: YEAR, MONT DAY, HOUR, MINUTE и SECOND. Существует два класса данных с интервальным типом: интервалы год—месяц и интервалы день—время. В первом случае данные включают только два поля — YEAR и/или MONTH. Данные второго типа могут состоять из произвольной последовательности полей DAY, HOUR, MINUTE, SECOND. Данные интервального типа определяются следующим образом:
INTERVAL {{start_field TO end_field} single_datetime_ field}
Start_field = YEAR | MONTH | DAY | HOUR | MINUTE
[(interval leading field precision)]
end_field = YEAR | MONTH | DAY | HOUR | MINUTE | SECOND
[(fractional seconds precision)]
single_datetime_field = start field | SECOND
[(interval leading field precision
[,fractional seconds precision])]
Во всех случаях для параметра start_field необходимо указать размерность первого поля (interval leading field precision), которая по умолчанию принимается равной двум. Например: INTERVAL YEAR(2) TO MONTH. Это объявление описывает интервал времени, значение которого может находиться между 0 годом, 0 месяцем и 99 годом, 11 месяцем. Еще один пример: INTERVAL HOUR TO SECOND(4). Это объявление описывает интервал времени, значение которого может меняться от 0 часов, 0 минут, 0 секунд до 99 часов, 59 минут 59.9999 секунды. (Значность первого поля по умолчанию устанавливается равной 2, а число дробных десятичных знаков для секунд явно задано равным 4.)
Оператор создания таблицы имеет следующий вид (упрощенный):
CREATE TABLE <имя_та6лицы>
(<имя_поля> <тип_данных> [NOT NULL]
[,<имя_поля> <тип_данных> [NOT NULL]]...).
Обязательными операндами оператора являются имя создаваемой таблицы и имя хотя бы одного поля с указанием типа данных, хранимых в этом поле.
В результате выполнения этого оператора будет создана таблица, имя которой определяется параметром table_name, состоящая из одного или более столбцов с именами, задаваемыми параметрами column_name, содержащими данные с типом, указанным параметрами data_ type. Ключевое слово NULL используется для указания того, что в данном столбце могут содержаться значения NULL. Значение NULL отличается от пробела или нуля — оно используется для указания того, что данные недоступны, опущены или недопустимы. Если указано ключевое слово NOT NULL, то будут отклонены любые попытки поместить значение NULL в данный столбец. Если указано значение NULL, помещение значений NULL в столбец будет разрешено. По умолчанию стандарт ISO предполагает наличие ключевого слова NULL.
Столбцы первичных ключей всегда должны определяться с указанием ключевого слова NOT NULL — это гарантирует, что первичный ключ таблицы не будет содержать пустых значений, способных вызвать нарушение ссылочной целостности данных. Если определитель NOT NULL не будет указан, в ключевой столбец таблицы могут быть внесены пустые значения, что вызовет нарушение ссылочной целостности данных. Для исключения подобных ошибок потребуется создать специальные программы, предназначенные для поддержки ссылочной целостности данных в системе. Столбцы внешних ключей также часто но не всегда) являются кандидатами на использование ключевого слова NOT NULL.
CREATE TABLE | DBF TableName1 [NAME LongTableName] [FREE]
( FieldName1 FieldType [( nFieldWidth [, nPrecision] )] [NULL | NOT NULL]
[CHECK lExpression1 [ERROR cMessageText1]]
[AUTOINC [NEXTVALUE NextValue [STEP StepValue]]] [DEFAULT eExpression1]
[PRIMARY KEY | UNIQUE [COLLATE cCollateSequence]]
[REFERENCES TableName2 [TAG TagName1]] [NOCPTRANS]
[, FieldName2 ... ]
[, PRIMARY KEY eExpression2 TAG TagName2 |, UNIQUE eExpression3 TAG TagName3
[COLLATE cCollateSequence]]
[, FOREIGN KEY eExpression4 TAG TagName4 [NODUP]
[COLLATE cCollateSequence]
REFERENCES TableName3 [TAG TagName5]] [, CHECK lExpression2 [ERROR cMessageText2]] )
| FROM ARRAY ArrayName
4. ALTER TABLE
Для внесения изменений в уже созданные таблицы стандартом ISO предусмотрен оператор ALTER TABLE. Определение оператора ALTER TABLE в стандарте ISO включает шесть параметров, предназначенных для выполнения следующих операций:
• добавления к таблице нового столбца;
• удаления столбца из таблицы;
• добавления в определение таблицы нового ограничения;
• удаления из определения таблицы существующего ограничения;
• задания для столбца значения по умолчанию;
• отмены установленного для столбца значения по умолчанию.
Оператор ALTER TABLE имеет следующий обобщенный формат:
ALTER TABLE table_name
[ADD [COLUMN] columnjiame data_type [NOT NULL] [UNIQUE] [DEFAULT default_option] [CHECK (search_condition) ] ]
[DROP [COLUMN] column_name [RESTRICT | CASCADE]]
[ADD [CONSTRAINT [constraintjname]} table_constraint_definition]
[DROP CONSTRAINT constraint_name [RESTRICT | CASCADE]] [ALTER [COLUMN] SET DEFAULT default^option]
[ALTER [COLUMN] DROP DEFAULT]
Здесь параметры имеют то же самое назначение, что и в определении оператора CREATE TABLE. Параметр table constraint_definition может принимать одно из следующих значений: PRIMARY KEY, UNIQUE, FOREIGN_КEY или CHECK. Предложение ADD COLUMN представляет собой определение столбца, аналогичное тому, которое используется в операторе CREATE TABLE. В предложении DROP COLUMN указывается имя столбца, который удаляется из определения таблицы. Это предложение включает дополнительный квалификатор, указывающий, следует ли выполнять каскадное распространение операции DROP. Этот квалификатор может принимать одно из следующих значений:
• RESTRICT — выполнение операции DROP отменяется, если на данный столбец ссылается какой-либо иной объект базы данных (например, определение представления). По умолчанию принимается, что данный квалификатор имеет значение RESTRICT;
• CASCADE — операция DROP выполняется, кроме того, автоматически удаляются ссылки на данный объект из всех объектов базы данных, в которых они присутствовали. Данная операция распространяется каскадным образом, поэтому, когда ссылка удаляется из ссылающегося на удаляемый столбец объекта, система автоматически проверяет, имеются ли где-либо в базе данных ссылки и на этот удаляемый элемент, после чего все найденные вторичные ссылки также удаляются, и т.д.
Это та же самая концепция, которая используется для квалификатора RESTRICT/ SCADE в операторе DROP TABLE
5. UPDATE
Оператор UPDATE позволяет изменять содержимое уже существующих строк указанной таблицы. Этот оператор имеет следующий формат:
UPDATE table_name
SЕТ column_namel = data_valuel [,column_name2=data_value2…]
[WHERE search_condition]
Здесь параметр table name представляет либо имя таблицы базы данных, либо имя обновляемого представления. В предложении SET указываются имена ого или более столбцов, данные в которых необходимо изменить. Предложение WHERЕ является необязательным. Если оно опущено, значения указанных столбцов будут изменены во всех строках таблицы. Если предложение WHERE присутствует, то обновлены будут только те строки, которые удовлетворяют условию поиска, заданному в параметре search_condition. Параметры data_value представляют новые значения соответствующих столбцов и должны быть совместимы с ними по типу данных.
6. INSERT
Существует две формы оператора INSERT. Первая предназначена для вставки единственной строки в указанную таблицу. Эта форма оператора INSERT имеет следующий формат:
INSERT INTO table_name [(column_list)]
VALUES (data_value_list)
Здесь параметр table_name (Имя таблицы) может представлять либо имя таблицы данных, либо имя обновляемого представления (раздел 14.1). Параметр column-list (Список столбцов) представляет собой список, состоящий из имен одного или более столбцов, разделенных запятыми. Параметр column_list является необязательным. Если он опущен, то предполагается использование списка из имен всех столбцов таблицы, указанных в том порядке, в котором они были описаны в операторе CREATE TABLE. Если в операторе INSERT указывается конкретный список имен столбцов, то любые опущенные в нем столбцы должны быть объявлены при создании таблицы как допускающие значение NULL — за исключением случаев, когда при описании столбца использовался параметр DEFAULT (раздел 14.3.1). Параметр data_value_list (Список значений данных) должен следующим образом соответствовать параметру column_list:
• количество элементов в обоих списках должно быть одинаковым;
• должно существовать прямое соответствие между позицией одного и того же элемента в обоих списках, поэтому первый элемент списка data_value_list полагается относящимся к первому элементу списка column_list, второй элемент списка data_value_list — ко второму элементу списка column_list и т.д.;
• типы данных элементов списка data value_list должны быть совместимы с типом данных соответствующих столбцов таблицы.
Если размещать вставляемые в каждый столбец таблицы данные в порядке их расположения в таблице, то указывать список столбцов необязательно. Не забывайте, что символьные значения (например, 'Alan') должны быть взяты в одинарные кавычки.
Вторая форма оператора INSERT позволяет скопировать множество строк одно таблицы в другую таблицу. Этот оператор имеет следующий формат:
INSERT INTO table_name [(column_list)]
SELECT …
Здесь параметры table_name и column_list имеют тот же формат и смысл, что и при вставке в таблицу одной строки. Предложение SELECT может представлять собой любой допустимый оператор SELECT. Строки, вставляемые в указанную таблицу, в точности соответствуют строкам результирующей таблицы, созданной при выполнении вложенного запроса. Все ограничения, указанные выше для первой формы оператора INSERT, применимы и в этом случае.
7. DELETE
Оператор DELETE позволяет удалять строки данных из указанной таблицы. Оператор имеет следующий формат:
DELETE FROM table_name
[WHERE search condition]
Как и в случае операторов INSERT и UPDATE, параметр table_name может представлять собой либо имя таблицы базы данных, либо имя обновляемого представления. Параметр search condition является необязательным — если он опущен, из таблицы будут удалены все существующие в ней строки. Однако сама по себе таблица удалена не будет. Если необходимо удалить не только содержимое таблицы, но и ее определение, следует использовать оператор DROP TABLE. Если предложение WHERE присутствует, из таблицы будут удалены только те строки, которые удовлетворяют условию отбора, заданному параметром search_condition.
Приложение 7
Система управления базами данных Microsoft Visual FoxPro 6.0. РАБОТА С ФОРМАМИ И ОТЧЕТАМИ
1. Общие сведения
Система Microsoft Visual FoxPro 6.0 содержит все необходимые средства для создания и управления высокопроизводительными 32-х разрядными приложениями и компонентами баз данных. Надежные инструментальные средства и объектно-ориентированный язык, специализированный для работы с данными, идеально подходят для создания современных масштабируемых многоуровневых приложений, интегрируемых в архитектуру клиент/сервер и Интернет
Visual FoxPro предоставляет два способа создания нового файла для большинства типов файлов, включая формы и отчеты:
• создать новый файл для проектирования объекта в среде визуального программирования;
• вызвать мастер файла (Wizard), облегчающий создание простых приложений.
При создании нового файла формы (отчета) необходимо вручную размещать поля источника данных в окне формы (отчета).
При вызове мастера необходимо ответить на его вопросы в последовательности диалоговых окон. Форма (отчет) создастся автоматически.
2. Работа с формами
Формы используются для ввода и редактирования данных в таблицах. Формы предоставляют пользователю удобный интерфейс для доступа к хранимым данным с возможностью отображения их в требуемом виде.
2.1. Создание формы
В Visual FoxPro существует возможность создавать формы как на основании данных из одной таблицы, так и на основании данных из нескольких таблиц.
При создании форм через мастер форм Visual FoxPro предлагает два типа формы: Form Wizard (форма на основе одной таблицы) или One-to-Many Form Wizard (форма на основе двух связанных таблиц).
2.1.1. Создание форм по одной таблице с помощью мастера
Рассмотрим по шагам проектирование формы.
Для создания новой формы необходимо выбрать пункт меню File→New в главном меню. В окне создания нового объекта выбираем опцию создания формы (Form) и нажимаем на кнопку мастера форм (Wizard). В появившемся окне Wizard Selection (выбор мастера) – рис.П.7.1 – выбираем тип создаваемой формы. В нашем случае это однотабличный тип (Form wizard).
Рис.П.7.1. Выбор мастера
После нажатия кнопки ОК запускается мастер проектирования формы. Мастер проектирования форм предлагает последовательность диалоговых окон. Переход от одного окна к другому происходит после нажатия кнопки Next (переход к следующему окну) или Back (возврат к предыдущему окну).
В первом окне мастера необходимо указать таблицу, для которой создается форма, и выбрать поля этой таблицы, размещаемые на форме (рис.П.7.2). В области Databases and tables расположены два списка. Верхний список содержит список открытых баз данных, нижний – список таблиц выбранной базы данных или свободных таблиц.
Рис.П.7.2. Выбор таблицы
Из нижнего столбца области Databases and tables мы выбираем таблицу, по которой и будем создавать форму. После выбора таблицы в списке Available fields появится перечень всех полей таблицы (рис.П.7.3).
Рис.П.7.3.Выбор полей таблицы
Из данного списка с помощью кнопок в список Selected fields переносим поля, которые хотим разместить на создаваемой форме.
Кнопки , – перемещение одного элемента списка.
Кнопки , – перемещение всего списка.
Выбрав поля, которые будут отображаться на форме, нажимаем кнопку Next для перехода к следующему шагу.
На втором шаге мастера создания форм предлагается выбрать стиль оформления формы (Style) и определить вид кнопок (Button type) (рис.П.7.4).
Рис.П.7.4. Выбор стиля формы
В появившемся диалоговом окне мастера устанавливаем понравившийся нам стиль отображения формы и вид кнопок. Нажимаем кнопку Next для перехода к следующему шагу.
На третьем шаге можно определить порядок просмотра записей таблицы в форме, т.е. задать критерии сортировки данных, отображаемых на форме. В списке Available fields or index tag отображаются все возможные поля таблицы, на основе которой строится форма, и с помощью кнопки Add их можно переместить в колонку Selected fields (рис.П.7.5). С помощью кнопки Remove выбранные поля можно удалить из списка полей для сортировки данных.
Рис.П.7.5. Выбор порядка просмотра
По полям, указанным в колонке Selected fields будет проводиться сортировка данных в форме. Нажимаем кнопку Next для перехода к следующему шагу.
На четвертом шаге создания формы с помощью мастера задаем заголовок формы в поле Type a title for your form, просматриваем предварительный результат (кнопка Preview), а также указываем действие с созданной формой, выбрав одну из опций (рис.П.7.6):
Save form for later use – сохранение формы;
Save and run form – сохранение формы и ее запуск;
Save form and modify it in the form designer – сохранение формы и открытие конструктора форм для модификации формы.
При нажатии на кнопку Finish мастер создания форм будет закрыт и выполнено указанное пользователем действие с формой.
Рис.П.7.6. Завершение проектирования формы
Сформированная мастером форм форма является законченным и отлаженным продуктом. При необходимости эту форму можно модифицировать таким же образом, как и форму, созданную непосредственно из нового файла, с помощью конструктора форм.
2.1.2. Создание форм по нескольким таблицам с помощью мастера
Рассмотрим создание формы на основе двух таблиц.
Форма «один-ко-многим» (One-to-Many Form) позволяет одновременно работать с данными двух логически связанных между собой таблиц.
После выбора пункта меню File→New в диалоговом окне New выбираем опцию создания формы (Form) и нажимаем на кнопку мастера форм (Wizard). В появившемся диалоговом окне Wizard Selection (выбор мастера), см. рис.П.7.1, выбираем тип создаваемой формы One-to-Many Form Wizard.
После нажатия кнопки ОК появляется первое диалоговое окно мастера (рис.П.7.7), в котором необходимо указать родительскую таблицу для создаваемой формы и выбрать поля этой таблицы, размещаемые в форме. В список Selected fields переносим поля родительской таблицы, которые хотим разместить на создаваемой форме.
Рис.П.7.7. Выбор родительской таблицы
На следующем шаге (рис.П.7.8) выбираем дочернюю таблицу и поля этой таблицы, которые будут размещены на форме.
Рис.П.7.8. Выбор дочерней таблицы
На третьем шаге (рис.П.7.9) проверяем поля, по которым устанавливается связь между таблицами. Эти поля должны иметь одинаковый тип данных, но названия их не обязательно должны совпадать.
Рис.П.7.9. Установка связи между таблицами
На четвертом шаге выбираем понравившийся стиль отображения формы и вид кнопок, на пятом шаге – указываем поле или несколько полей, по которым будет проводиться сортировка данных в форме (окна аналогичны приведенным на рис.П.7.4, П.7.5).
На шестом шаге задаем заголовок формы в поле Type a title for your form, а также указываем действие с созданное формой. Нажимаем кнопку Finish.
В результате ввода информации в эти шесть окон мастер формы автоматически создаст форму для редактирования данных из двух связанных таблиц.
В нижней части окна формы, созданной с помощью мастера форм, расположен элемент управления из библиотеки классов Visual FoxPro – группа командных кнопок для управления источником данных. Эти кнопки позволяют перемещаться по таблице, выполнять поиск, удалять записи или вставлять новые записи.
2.2. Запуск формы
Запустить сохраненную форму можно несколькими способами:
• кнопка Run на стандартной панели инструментов;
• пункт меню Run Form из меню Form;
• ввод в командном окне команды
do form <имя_формы_без_расширения>.
2.3. Модификация формы
Для внесения изменений в созданную форму в командном окне вводим команду MODIFY FORM <имя_формы>. Visual FoxPro откроет окно конструктора формы и соответствующий ему набор инструментов (рис.П.7.10).
Рис.П.7.10. Окно конструктора формы
Набор инструментария Form Controls, содержит следующие кнопки (слева направо, сверху вниз):
Select Object – выбор объекта;
View Classes – загрузка других библиотек класса;
Label – элемент управления «метка»;
Text Box – элемент управления «текстовый блок»;
Edit Box – элемент управления «многострочное текстовое поле»;
Command Button – элемент управления «командная кнопка»;
Command Group – элемент управления «группа командных кнопок»;
Option Group – элемент управления «группа радиокнопок»;
Check Box – элемент управления «переключатель»;
Combo Box – элемент управления «раскрывающийся список»;
List Box – элемент управления «панель списка»;
Spinner – элемент управления «счетчик»;
Grid – элемент управления «окно таблицы»;
Image – элемент управления «рисунок»;
Timer – элемент управления «таймер»;
PageFrame – элемент управления «страничный блок»;
ActiveX Control (OLE Control) – элемент управления «контейнер OLE»;
ActiveX Bound Control (OLE Bound Control) – элемент управления «внедренный объект OLE»;
Line – элемент управления «линия»;
Shape – элемент управления «контур»;
Container – контейнер;
Separator – элемент управления «разделитель»;
Builder Lock – режим вызова построителя объектов;
Button Lock – переключение режима многократного/однократного размещения объектов.
Необходимым элементом, используемым при разработке экранных форм, является окно свойств (Properties). С помощью этого окна можно редактировать свойства, события и методы экранной формы и ее объектов.
Окно свойств можно условно разделить на две части: в левой, на сером фоне, перечислены названия всех свойств, методов и событий объектов, а в правой, на белом фоне, – значения этих свойств (событий, методов).
Окно свойств имеет пять вкладок:
All – отображает все свойства, методы и события для данного объекта;
Data – отображает только те свойства, которые имеют отношение к данным;
Methods – отображает все методы и события объекта;
Layout – отображает свойства, которые «отвечают» за отображение объекта на экране;
Other – другие свойства объекта.
2.4. Удаление формы
Удалить файл формы с диска можно с помощью команды
delete file <имя_формы>.scx
3. Работа с отчетами
Отчеты используются для отображения информации, содержащейся в БД, в многостраничных выходных документах и позволяют осуществлять в нем необходимую группировку данных, отображать итоговые и расчетные данные.
3.1. Создание отчетов
Visual FoxPro предлагает три пути создания отчетов:
• создание простого или многотабличного отчета с применением мастера отчета (Report Wizard);
• создание простого отчета для одной таблицы с применением быстрого формирования отчета (Quick Report);
• изменение существующего отчета или создание нового отчета в окне проектирования отчета Report Designer.
Рассмотрим создание отчета с помощью мастера создания отчетов.
Создание отчета через мастер создания отчетов аналогично созданию форм через мастер создания форм.
Мастер отчетов Visual FoxPro предлагает выбрать один из трех видов формируемого отчета:
• Group/Total Report Wizard (отчет с группируемыми данными и частичными суммами);
• One-to-Many Report Wizard (отчет с данными из двух связанных таблиц);
• Report Wizard (простой многоколонный отчет).
3.1.1. Создание отчета по одной таблице с помощью мастера
Создадим простой отчет.
Для этого выбираем пункт меню File→New. В окне создания нового объекта выбираем опцию создания отчета (Report) и нажимаем на кнопку мастера отчетов (Wizard). В появившемся окне Wizard Selection выбираем тип создаваемого отчета Report wizard (рис.П.7.11).
Рис.П.7.11. Выбор типа отчета
Так же, как и в мастере форм, мастер отчетов предлагает ответить на вопросы нескольких последовательных окон.
После нажатия кнопки ОК в окне Wizard Selection, появляется первое диалоговое окно мастера, в котором необходимо указать таблицу, для которой создается отчет и выбрать размещаемые в этом отчете поля. Аналогично созданию формы, выбираем таблицу, по которой и будем создавать отчет. В список Selected fields переносим поля для отображения в отчете из списка Available fields (рис.П.7.12).
Рис.П.7.12. Выбор полей
На втором шаге необходимо указать поля, по которым будет осуществляться группировка данных в отчете (рис.П.7.13).
Затем выбираем стиль отображения отчета (рис. П.7.14), ориентацию страницы – книжная или альбомная (рис.П.7.15) и поля, по которым требуется упорядочение данных в отчете (рис.П.7.16).
Рис. П.7.13. Выбор полей для группировки
Рис. П.7.14. Выбор стиля отчета
Рис. П.7.15. Выбор ориентации страницы
Рис. П.7.16. Сортировка данных в отчете
Задаем заголовок отчета в поле Type a title for your report. На этом же шаге выбираем один из трех вариантов дальнейшей работы с отчетом (рис. П.7.17):
• Save report and modify it in the Report Designer – созданный отчет сохраняется на диске под указанным именем и открывается в конструкторе отчетов для модификации;
• Save report for later use – созданный отчет сохраняется на диске под указанным именем;
• Save and print report – созданный отчет сохраняется на диске под указанным именем и выводится на печать.
Рис. П.7.17. Заключительный этап проектирования отчета
В завершение этих действий Visual FoxPro автоматически сформирует отчет для указанной таблицы. Сформированный отчет записывается в файл с расширением .FRX. В дальнейшем сохраненный отчет можно изменять в конструкторе отчета Report Designer.
3.1.2. Создание отчета по двум таблицам с помощью мастера
Создадим отчет на основе двух таблиц. Для этого выбираем пункт меню File→New, в диалоговом окне New выбираем опцию создания отчета (Report) и нажимаем на кнопку мастера форм (Wizard). В появившемся диалоговом окне Wizard Selection выбираем тип создаваемого отчета One-to-Many Report Wizard (см. рис.П.7.11).
После нажатия кнопки ОК, появляется первое диалоговое окно мастера, в котором необходимо указать родительскую таблицу для создаваемого отчета и выбрать поля этой таблицы, размещаемые в отчете. В список Selected fields мы переносим поля родительской таблицы, которые хотим разместить на создаваемой форме.
На следующем шаге выбираем дочернюю таблицу и поля, которые будут размещены на форме от второй таблицы.
На третьем шаге выбираются поля, по которым осуществляется связь между выбранными таблицами.
Четвертый шаг – указываем поле, по которому идет сортировка.
На пятом шаге выбираем стиль создаваемого отчета. На последнем этапе задаем заголовок отчета, используя для этого поле ввода Type a title for your report. На этом же шаге выбираем один из трех вариантов дальнейшей работы с отчетом.
3.2. Печать отчета
Для просмотра отчета используется пункт меню Preview из контекстного меню или одноименная кнопка на стандартной панели инструментов. Еще один способ – выполнить команду из командного окна REPORT FORM <имя_отчета> PREVIEW. При выборе данной команды отчет открывается для предварительного просмотра.
Вывод отчета на печать тоже осуществляется несколькими способами:
• пункт меню Print из системного меню File;
• пункт меню Run Report из меню Report;
• команда REPORT FORM <имя_отчета> TO PRINTER из командного окна.
3.3. Модификация отчета
Чтобы редактировать отчет, необходимо либо через пункт меню FileOpenReport открыть необходимый отчет, либо выполнить команду в командном окне: MODIFY REPORT <имя_отчета_без_расширения>. В результате будет открыт конструктор отчетов (Report Designer), в котором осуществляется редактирование отчета.
Вся рабочая область конструктора отчетов по умолчанию разделена на три полосы, ограничиваемые разделительными строками. Наименование полосы отображается на разделительной строке, находящейся непосредственно под этой полосой. Также в отчете могут использоваться дополнительные полосы. Назначения полос приведены в таблице П.7.1.
В областях отчета можно размещать поля данных, выбрав соответствующий элемент Field в наборе инструментария Report Controls (рис.П.7.18) и указав мышью местоположение объекта в отчете.
При этом в зависимости от установленного режима Button Lock (многократное размещение объектов) выполняются следующие действия:
• по каждому щелчку мыши встраивается следующий объект;
• встраивается только один объект, который и остается выделенным.
Набор инструментария Report Controls (см. рис.П.7.18), содержит следующие кнопки (слева направо, сверху вниз):
Select Object – выбор объекта;
Label – метка;
Field – поле данных;
Line – линия;
Rectangle – прямоугольник;
Rounded Rectangle – прямоугольник со скругленными углами;
Picture/OLEBoundControl – рисунок;
Button Lock – переключение режима многократного размещения объектов.
Рис.П.7.18. Инструментарий Report Controls
Таблица П.7.1. Назначение полос конструктора отчетов
Наименование полос
Назначение
Title
Здесь размещается информация, появляющаяся перед основным отчетом. Это может быть имя отчета или любые другие данные, помещаемые только вверху первой страницы отчета.
Page Header
Данные, помещенные в полосу, печатаются в начале каждой страницы (верхний колонтитул). Например, название отчета, текущая дата или номер страницы.
Group Header
При использовании группировки данных в отчете информация из этой области печатается перед печатью самой группы данных. Это заголовок для группы.
Detail
Это полоса является основной и содержит данные полей из таблицы или результат вычислений над ними.
Page Footer
Данные, помещенные в полосу, печатаются в конце каждой страницы (нижний колонтитул). Например, дата, номер страницы и итоговые значения по данным текущей страницы.
Group Footer
Итоги по группе при использовании группировки данных.
Summary
В итоговой части отчета содержится информация, повторяющаяся один раз после основного отчета и содержащая итоговые значения или заключительный текст.
3.4. Удаление отчета
Удалить файл отчета с диска можно с помощью команды:
delete file <имя_отчета>.frx
4. Работа с меню
Visual FoxPro позволяет создавать два типа меню: обычное меню в виде строки, т.е. так называемую линейку главного меню (Menu), и всплывающее контекстное меню, т.е. самостоятельное ниспадающее меню (Shortcut). Описание меню хранится в файлах с расширениями MNX и MNT, сгенерированный текст программы меню хранится в файле с расширением MPR.
4.1. Создание меню
Для создания меню выбираем пункт меню File→New, в диалоговом окне New выбираем опцию создания меню (Menu) и нажимаем на кнопку New File. В появившемся диалоговом окне New Menu выбираем тип создаваемого меню Menu (рис.П.7.19)
Рис. П.7.19. Выбор типа меню
Окно New Menu также можно открыть через командное окно командой Create menu.
В окне конструктора меню (рис. П.7.20) необходимо определить пункты меню, определить подменю (если таковое предусматривается) и описать действия, выполняемые при выборе пунктов меню.
Рис. П.7.20. Поля окна проектирования меню
В столбце Prompt записываются названия пунктов меню. Раскрывающийся список столбца Result позволяет определить тип действия при выборе пункта меню – команда (Command), команды системного меню (Pad Name), подменю (Submenu) или программа (Procedure). Раскрывающийся список Menu Level позволяет переключаться между уровнями меню. Кнопки, расположенные в правой части конструктора, имеют следующее назначение:
Insert – добавляет новый пункт меню;
Insert Bar – позволяет разместить в пользовательском меню команды системного меню Visual FoxPro;
Delete – удаляет указанный пункт меню;
Preview – предварительный просмотр внешнего вида меню.
4.2. Запуск меню
Для создания выполняемого файла (программы, запускающей меню) необходимо сгенерировать код программы, выбрав пункт меню Menu→Generate главного меню FoxPro (данный пункт меню доступен при активном окне проектирования меню). Программа, запускающая меню, имеет расширение .MPR. Запустить эту программу из командного окна можно командой
DO <имя_меню>.MPR.
Для возврата к основному меню Visual FoxPro необходимо использовать команду:
SET SYSMENU TO DEFAULT.
4.3. Модификация меню
Для внесения изменений в созданное меню в командном окне вводим команду MODIFY MENU <имя_меню>. Visual FoxPro откроет конструктор меню. После внесения изменений в меню необходимо повторно сгенерировать код программы меню.
4.4. Удаление меню
Удалить файл меню с диска можно с помощью команды
delete file <имя_меню>.mpr
Приложение 8
ОРГАНИЗАЦИЯ И СТРУКТУРА ИНДЕКСОВ БД. ОСНОВНЫЕ СВЕДЕНИЯ
Рассматриваемые в контексте понятий «база данных» и «информационная система» элементы реального мира, информацию о которых необходимо сохранять и обрабатывать, будем называть объектами. Объект может быть материальным (например, «служащий», «изделие» или «населенный пункт») и нематериальным (например, «имя», «понятие», «абстрактная идея»).
Объект имеет различные свойства (например, цвет, вес, имя), которые важны в момент обращения к объекту с какой-либо целью его использования (например, выбор объекта среди множества других).
Однако во всех случаях человек, работая с информацией, имеет дело с абстракцией, представляющей интересующий его фрагмент реального мира (т. н. Предметной областью) - той совокупностью характеристических свойств (атрибутов), которые важны для решения его прикладной задачи.
В задачах обработки информации, и в первую очередь в алгоритмизации и программировании, атрибуты именуют (обозначают) и приписывают им значения.
В процессах обработки рассматривается совокупность отдельных экземпляров объектов, информацию о свойствах каждого из которых надо сохранять (записывать) как данные, чтобы при решении задач их можно было найти и выполнить необходимые преобразования. Таким образом, программисту или пользователю необходимо иметь возможность обращаться к отдельным, нужным ему записям (описаниям объектов) или отдельным элементам данных. В зависимости от уровня программного обеспечения прикладной программист может использовать следующие способы:
1. Задать машинный адрес данных и в соответствии с физическим форматом записи прочитать значение (когда программист должен быть «навигатором»).
2. Сообщить системе имя записи или элемента данных, которые он хочет получить, и, возможно, организацию набора данных. В этом случае система сама произведет выборку (по предыдущей схеме), но для этого она должна будет использовать вспомогательную информацию о структуре данных и организации набора.
Информация об имени элемента данных и организации набора данных по существу будет избыточной по отношению к объекту, однако общение с базой данных не будет требовать от пользователя знаний программиста и позволит переложить заботы о размещении данных на систему.
1. Идентификация записей
В качестве ключа, обеспечивающего доступ к записи, можно использовать идентификатор – отдельный элемент данных. Ключ, который идентифицирует запись единственным образом, называется первичным (главным). Такой ключ используется для поиска информации о конкретном экземпляре объекта. Иногда в качестве идентификатора используют составной сцепленный ключ – несколько элементов данных, которые в совокупности обеспечат уникальную идентификацию каждой записи набора данных.
Если необходимо отыскать некоторую группу записей, имеющих определенное общее свойство, используется так называемый вторичный или альтернативный ключ. Вторичный (альтернативный) ключ – это ключ, идентифицирующий группу записей, обладающих общим свойством. Набор данных может иметь несколько вторичных ключей, необходимость введения которых определяется практической потребностью – оптимизацией процессов поиска записей по соответствующему ключу.
Понятие ключа является логическим и опирается на значения атрибутов. Для того чтобы реализовать выбор записей на физическом уровне, необходимо построить дополнительную структуру, называемую индексом. Таким образом, индекс - физическая реализация ключа, обеспечивающая доступ к записям, соответствующим отдельным значениям ключа.
Один из способов использования вторичного ключа в качестве входа - организация инвертированного списка, каждый вход которого содержит значение ключа вместе со списком идентификаторов соответствующих записей. Данные в индексе располагаются в возрастающем или убывающем порядке, поэтому алгоритм поиска нужного значения довольно прост и эффективен, а после нахождения значения запись локализуется по указателю физического расположения. Недостатком индекса является то, что он занимает дополнительное пространство и его надо обновлять каждый раз, когда запись удаляется, обновляется или добавляется. На рис.П.8.2 приведен инвертированный список для ключа «Должность» таблицы, представленной на рис.П.8.1.
В общем случае инвертированный список может быть построен для любого ключа, в том числе составного.
В контексте задач поиска можно сказать, что существуют два основных способа организации данных. Первый соответствует примеру, приведенному на рис.П.8.1, и представляет прямую организацию массива. Второй способ является инверсией первого, он соответствует рис.П.8.2. Прямая организация массива удобна для поиска по условию «Каковы свойства указанного объекта?», а инвертированная – для поиска по условию «Какие объекты обладают указанным свойством?».
2. Формы организации индексов
Логически индекс есть бинарное отношение I(v,a), где v – значение атрибута, а a – список адресов элементов хранения (записей, кортежей или документов), соответствующих данному значению атрибута. Для повышения эффективности поиска отдельных значений и слияния/пересечения списков a значения v и адреса элементов в списке a хранятся в упорядоченном виде, что обеспечивает применение процедур быстрого поиска.
Рис. П.8.1. Пример набора записей табличного типа
Ассистент
7, 13, 14
Доцент
4, 5, 10, 11
Зав. каф.
1, 8
Проф.
2, 3, 9
Ст. преп.
6, 12
Рис. П.8.2. Инвертированный список для ключа «Должность»
Индекс I(v,a) часто называют также инвертированным индексом в том смысле, что значения атрибутов извлекаются из элементов хранения на поверхность, т.е. инвертируются. Каждый элемент a инвертированного индекса называют инвертированным списком.
Такое бинарное отношение на физическом уровне может быть реализовано двумя способами – в прямой и инвертированной форме.
Прямая реализация индекса представляет собой расширение бинарного отношения до совокупности записей, состоящих из двух полей – значения атрибута и адреса размещения одного элемента хранения (рис.П.8.3). При такой реализации отдельное значение атрибута повторяется в индексе столько раз, сколько оно встречается в файле данных, а длина индекса (в записях) совпадает с длиной файла данных.
Индекс
Значение атрибута
Адрес размещения
Фамилия И.О.
Год Рожд.
Должность
Кафедра №
1944
Иванов И.И.
1948
Зав. каф.
22
1945
Сидоров С.С.
1953
Проф.
22
1948
Гиацинтова Г.Г.
1945
Проф.
22
1950
Цветкова С.С.
1960
Доцент
22
1953
Козлов К.К.
1959
Доцент
22
1958
Петров П.П.
1960
Ст.преп.
22
1958
Лютикова Л.Л.
1977
Ассистент
22
1959
Рыбин Р.Р.
1950
Зав. каф.
23
1959
Китов К.К.
1944
Проф.
23
1960
Раков В.В.
1958
Доцент
23
1960
Соловьева С.С.
1958
Доцент
23
1966
Воробьева В.В.
1959
Ст.преп.
23
1976
Орлова О.О.
1966
Ассистент
23
1977
Осетров С.С.
1976
Ассистент
23
Рис.П.8.3. Структура индекса с прямой адресацией
В случае, когда списки a достаточно длинные, инвертированный индекс хранится в двух разных логических файлах, связанных указателями (файл-индекс и файл пересылок на рис.П.8.4). Такая организация называется хранением индекса в инвертированной форме, требует меньше памяти для хранения значений ключей и поиск в ней более эффективен.
Указатель пересылок может быть реализован несколькими способами. Например,
• указанием ссылки на первый и последний адреса размещения элементов для отдельного ключевого значения, как показано на рис.П.8.4;
• заданием ссылки на адрес размещения первого элемента и длиной списка адресов.
Файл-индекс
Файл пересылок
(инвертированный список)
Файл данных
Ключевые значения
Указатель пересылок
Адрес
размещения
Ключевое поле
Прочие элементы данных
…
…
…
Доцент
Доцент
Цветкова С.С. …
Доцент
Козлов К.К. …
…
…
…
…
Доцент
Раков В.В. …
…
Доцент
Соловьева С.С. …
…
…
Рис.П.8.4. Пример реализации инвертированного индекса
3. Физические структуры файлов
Ввод-вывод данных осуществляется путем взаимодействия программы с внешними файлами. Файл можно определить как логически непрерывный именованный набор данных на внешнем носителе.
Устройства, на которые осуществляется вывод данных или с которых осуществляется ввод, могут быть подразделены на следующие типы:
- устройства передачи информации битовым потоком;
- устройства посимвольного обмена информацией;
- устройства передачи информации записями (порциями).
Фактически тип устройства определяет, каким его «видит» прикладная программа через посредство драйвера устройства и программ операционной системы, ответственных за ввод-вывод информации. Одно и то же устройство может быть представлено как генератор потока символов (потоко-ориентированное устройство) или записей (записе-ориентированное). Поэтому скорее стоит говорить о типе файлов, расположенных на том или ином устройстве.
Могут быть рассмотрены следующие классификации файлов:
- по типу записей:
• файлы с записями фиксированной длины;
• файлы с записями переменной или неопределенной длины;
• файлы, образующие байтовый или битовый поток.
- по способу выборки информации
• файлы последовательного доступа;
• файлы прямого доступа.
Для всех этих типов файлов возникает проблема идентификации данных, размещенных на носителе (в файле).
Рассмотрим файлы прямого доступа. Для таких файлов характерны операции чтения и записи по произвольному адресу. Такие файлы размещаются на дисках, как устройствах прямого доступа.
Простейшим (и наиболее эффективным) способом быстрого нахождения необходимой записи по ее номеру в файле является использование записей с фиксированной длиной. Тогда физический адрес легко вычисляется как некоторое смещение относительно начала файла, пропорциональное номеру выбираемой записи, например:
если в файле F размещено N записей длиной l байт, то:
• общая длина всего файла - Length(F) = N • l байт;
• смещение i-й записи от начала файла - Adr(i) = l • (i – 1) байт.
Пусть в файле прямого доступа, содержащем записи длиной L, необходимо поменять местами пятую и шестую записи. Порядок решения такой задачи следующий:
• открыть файл на чтение-запись;
• проверить, содержатся ли в файле записи с номером 5 и 6 (т.е. длина файла должна быть больше либо равна 6∙L);
• определить позицию пятой записи и установить на нее указатель;
• прочитать пятую запись и поместить ее в переменную Record1;
• прочитать следующую (шестую) запись и поместить ее в переменную Record2;
• установить указатель в файле на пятую запись;
• записать содержимое Record2;
• записать содержимое Record1;
• закрыть файл.
Файлы прямого доступа могут быть типизированы. В этом случае они представляют собой линейную последовательность однотипных компонентов. Наиболее распространенный тип компонента для типизированных файлов – запись. Тип данных запись представляет собой наиболее общий метод получения структурных типов данных. Этот метод заключается в объединении элементов произвольных типов, причем сами эти элементы могут быть в свою очередь структурными. Отдельные элементы записи принято называть полями. Каждое поле данных определено с точки зрения занимаемого им размера (в байтах), а совокупная длина записи представляет собой сумму длин всех входящих в нее полей.
Таким образом, физическая структура файла, состоящего из записей, может быть представлена описанием отдельной записи: составом полей и типами и размерами данных для каждого поля. При этом тип данных поля определяет еще и множество операций и процедур обработки, возможных для значений этого поля.
В таблице П.8.1 приведено описание физической структуры файла, элементы которого представляют собой записи, содержащие информацию о результате сдачи экзамена.
Таблица П.8.1. Физическая структура записи файла
Имя поля
Тип данных
Размер (в байтах)
Описание
Family
строка
30
Фамилия
Name
строка
15
Имя
Patr
строка
20
Отчество
Group
строка
5
Номер группы
Course
целое
1
Курс
Subject
строка
30
Название предмета
Mark
целое
1
Оценка
Общий размер записи =
102