This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Федеральное агентство по образованию Ульяновский государственный технический университет
Г. П. Токмаков
БАЗЫ ДАННЫХ И ЗНАНИЙ Проектирование баз данных по технологии «клиент-сервер» и разработка клиентских приложений
Учебное пособие
Ульяновск 2005
УДК 681.3 (075) ББК 73я7 Т51 Рецензенты: д-р техн. наук, ст. науч. сотр. Иванов А. К. канд. техн. наук, доцент Андреев Д. В. Утверждено редакционно-издательским советом университета в качестве учебного пособия
Токмаков,Г. П. Т51
Базы данных и знаний. Проектирование баз данных по технологии «клиент-сервер» и разработка клиентских приложений: Учебное пособие / Г.П. Токмаков.- Ульяновск; УлГТУ, 2005. - 143 с. ISBN 5-89146-697-Х
Пособие содержит материал, необходимый для выполнения курсовой работы по проектированию баз данных и разработки клиентских приложений с использованием современного инструментария визуальной разработки. В пособии подробно изложены методика проектирования и этапы разработки баз данных с помощью CASE-средства ERwin и разработки пользовательских приложений с помощью среды разработки Delphi. Предназначено для студентов специальностей 522800 и 522300, а также может использоваться для других специальностей.
- 3ОГЛАВЛЕНИЕ ВВЕДЕНИЕ ...................................................................................................5 ГЛАВА 1. АНАЛИЗ ПРЕДМЕТНОЙ ОБЛАСТИ И ПРОЕКТИРОВАНИЕ БД .................................................................................................................6 1.1. ОПИСАНИЕ ПРЕДМЕТ НОЙ ОБЛАСТИ ..................................................6 1.1.1. Документы справочной информации.......................................................7 1.1.2. Документы учетной информации ........................................................... 8 1.2. ПОСТРОЕНИЕ ЛОГИЧЕСКОЙ МОДЕЛ И ДАННЫХ................................9 1.2.1. Информационные объекты .....................................................................9 1.2.2. Связи информационных объектов .........................................................13 1.2.3. Информационно-логическая модель ПРДО ...........................................15 1.2.4. Логическая структура реляционной БД ................................................. 15 ГЛАВА 2. ПРОЕКТИРОВАНИЕ БД С ПОМОЩЬЮ ПРОГРАММЫ ERwiN ......................................................................................................... 17 2.1. СОЗДАНИЕ ЛОГИЧЕСКОЙ МОДЕЛ И БД .............................................17 2.1.1. Создание сущностей .............................................................................17 2.1.2. Создание доменов ................................................................................19 2.1.3. Установка атрибутов сущности.............................................................24 2.1.4. Установка связей между сущностями ....................................................27 2.2. СОЗДАНИЕ ФИЗИЧЕСКОЙ МОДЕЛ И БД .............................................35 2.2.1. Выбор сервера......................................................................................35 2.2.2. Таблицы и колонки ...............................................................................36 2.2.3. Редактирование свойств полей ..............................................................39 2.2.4. Генерирование SQL-сценария создания БД............................................40 2.2.5. Код подключения к БД .........................................................................47 2.2.6. Генераторы и триггеры .........................................................................51 2.2.7. Хранимые процедуры ............................................................................56 2.2.8. Индексы ............................................................................................... 58 2.3. РАЗРАБОТКА ОТЧЕТОВ.......................................................................68 ГЛАВА 3. СОЗДАНИЕ КЛИЕНТСКОГО ПРИЛОЖЕНИЯ ДЛЯ РАБОТЫ С БД............................................................................................................ 69 3.1. СОЗДАНИЕ БАЗЫ ДАННЫХ.................................................................70 3.1.1. Создание «контейнера» базы данных ....................................................70 3.1.2. Создание псевдонима для серверной БД................................................72 3.1.3. Создание SQL-сценария и объектов базы данных ..................................73 3.2. ОБОЛОЧКА КЛ ИЕНТСКОГО ПРИЛОЖЕНИЯ.......................................74 3.2.1. Создание проектной группы ................................................................. 74 3.2.2. Создание модуля UMAIN....................................................................... 75 3.2.3. Создание модуля UDM ......................................................................... 76
- 4-
3.3. СВЯЗЬ С БАЗОЙ ДАННЫХ ................................................................... 80 3.3.1. Создание проекта dll_login ................................................................... 80 3.3.2. Создание программного класса............................................................. 81 3.3.3. Создание формы диалога...................................................................... 83 3.3.4. Организация вызова входного диалога в главном модуле....................... 85 3.3.5. Общая схема работы приложения при подключении к БД...................... 89 3.4. ДИАЛОГОВЫЕ ОКНА .......................................................................... 90 3.4.1. Общая схема создания диалоговых окон ............................................... 90 3.4.2. Подготовка к созданию диалоговых окон .............................................. 92 3.4.3. Диалоговые окна для таблицы GROUPS................................................ 94
ЗАКЛЮЧЕНИЕ ........................................................................................ 122 ПРИЛОЖЕНИЕ А. СПИСОК МАКРОКОМАНД ERWIN........................ 123 ПРИЛОЖЕНИЕ В. ТРЕБОВАНИЯ ПО ВЫПОЛНЕНИЮ ПОЯСНИТЕЛЬНОЙ ЗАПИСКИ .............................................................. 131 ПРИЛОЖЕНИЕ С. ВАРИАНТЫ ЗАДАНИЙ ПО КУРСОВОЙ РАБОТЕ ................................................................................................. 132 С. 1. ОБЩЕЕ ЗАД АНИЕ ДЛЯ ВСЕХ ВАРИАНТОВ..................................... 132 С.2. ВАРИАНТЫ ПРЕДМЕТНЫХ ОБЛАСТЕЙ ........................................... 133 БИБЛИОГРАФИЧЕСКИЙ СПИСОК..............................................................143
- 5ВВЕДЕНИЕ Предметом учебного пособия является изучение и освоение методов проектирования информационных систем на основе баз данных по клиент-серверной технологии. В качестве средств разработки использованы CASE-средство разработки БД ERwin и визуальная среда разработки программ Delphi. Всякая прикладная программа является отображением какой-то части реального мира и поэтому содержит его формализованное описание в виде данных. Крупные массивы данных размещают отдельно от исполняемого кода программы и организуют в виде БД. Для работы с данными используют особые программные комплексы, СУБД. Историю развития концепции баз данных можно представить как последовательность шагов, каждый из которых делал приложения более глобальными. На современном этапе развития средств обработки данных доминирует клиентсерверная архитектура, в рамках которой приложение может взаимодействовать с другими приложениями в рамках локальной сети путем обмена данными через сервер баз данных. В архитектуре «клиент-сервер» СУБД принимает запросы каналов и возвращает результаты по сети. Такая СУБД называется сервером БД. С развитием компьютерной техники возросла сложность информационных систем и объемы данных. В нас тоящее время разработка таких систем - это задача для коллективов разработчиков, требующая специальных методик и инструментов. Разработку информационной системы принято разбивать на следующие этапы: •- этап анализа предметной области; •- этап проектирования; •- этап кодирования, т. е. разработки пользовательских приложений. Этап анализа предметной области включает в себя выделение информационных объектов и их атрибутов, установление связей между информационными объектами и определение их характеристик. В результате выполнения анализа предметной области создается логическая модель будущей базы данных. На этапе проектирования создается физическая модель БД, которая, в отличие от логической модели, строится с привязкой к конкретной СУБД. Для удобства работы с созданной БД строятся так называемые пользовательские приложения, кодируемые на одном из языков программирования. Время разработки сложных систем сравнимо с предполагаемым циклом их жизни, и сокращение времени разработки с тановится одной из важнейших задач ее организации. Поэтому будущий специалист должен владеть инструментарием быс трой разработки БД и приложений для работы с ней. С этой целью в данном пособии рассматриваются CASE-средство ERwin (средство визуальной разработки БД) и среда быстрого программирования Delphi.
- 6ГЛАВА 1. АНАЛИЗ ПРЕДМЕТНОЙ ОБЛАСТИ И ПРОЕКТИРОВАНИЕ БД Перед созданием БД необходимо располагать описанием выбранной предметной облас ти (ПрдО), которое должно охватить реальные объекты и процессы, определить все необходимые ис точники информации для удовлетворения предполагаемых запросов пользователя и определить потребности в обработке данных. На основе такого описания на этапе проектирования БД определяется состав и структура данных ПрдО, которые должны находится в БД и обеспечивать выполнение необходимых запросов и задач пользователя. Структура данных ПрдО отображается в виде логической модели, на основе которой легко создается реляционная БД. При разработке модели данных могут использоваться два подхода. В первом подходе сначала определяются основные задачи, для решения которых строится база, выявляются потребности задач в данных и, соответственно, определяется состав и структура информационных объектов. При втором подходе сразу устанавливаются типовые объекты ПрдО. Наиболее рационально сочетание обоих подходов. Это связано с тем, что на начальном этапе, как правило, нет исчерпывающих сведений обо всех задачах, а современные технологии проектирования позволяют на любом этапе разработки внести изменения и модифицировать ее структуру без ущерба для введенных ранее данных. Поэтому в процессе разработки БД выполняются следующие этапы проектирования: • проводится анализ ПрдО, в ходе которого выявляются информационные объекты, соответс твующие требованиям нормализации данных; • затем определяются связи между выделенными объектами; • на основе построенной информационно-логической (концептуальной) модели строится логическая модель БД, где каждый информационный объект отображается реляционной таблицей, а связи между таблицами соответствуют связям между информационными объектами. 1.1. ОПИСАНИЕ ПРЕДМЕТНОЙ ОБЛАСТИ Необходимо построить БД, обеспечивающую учебный процесс текущего семестра на кафедре и содержащую следующую информацию: •- списки студентов групп; •- перечень изучаемых предметов; • преподавательский состав кафедр, обеспечивающих учебный процесс; • сведения о лекционных и практических занятиях в каждой из групп; • результаты сдачи экзаменов (зачетов) по каждой дисциплине.
—7—
В результате анализа учебного процесса выявляются документы, являющиеся источниками данных для создания БД. Следует отметить, что документы ПрдО не только дают возможность выявить структуру данных, но также являются основой для разработки форм ввода-вывода и отчетов. В результате анализа мы выявим информационные объекты двух типов: документы справочной информации, касающиеся статичных образований, т. е. объектов реальной действительности, и документы учетной информации, т. е. процессов, происходящих в описываемой ПрдО. 1.1.1. ДОКУМЕНТЫ СПРАВОЧНОЙ ИНФОРМАЦИИ Справочная информация содержится в документах: «Список студентов групп», «Список преподавателей кафедр», «Список изучаемых предметов» . Форма списка студентов групп приведена на рис. 1. Интуитивно из этого списка можно выделить два объекта: ГРУППА и СТ УДЕНТ. По этим спискам можно получить информацию о том, к какой группе относится студент, его год рождения, адрес и набранные баллы на вступительных экзаменах. Список студентов группы №_______
Рис. 1. Форма документа со списком студентов
Форма документа со списком преподавателей приведена на рис. 2. Этот список содержит сведения еще о двух объектах ПрдО: КАФЕДРА и ПРЕПОДАВАТЕЛЬ . Этот список аналогичен предыдущему, и по нему также можно опредепить не только сведения о кафедрах, но и о преподавателях..
Рис. 2.
Форма документа со списком преподавателей Список преподавателей кафедры
- 8-
Здесь содержатся сведения о том, на какой кафедре работает преподаватель, название, код и телефон кафедры, фамилия, имя, отчес тво заведующего данной кафедрой, списочный состав кафедры. 1.1.2. ДОКУМЕНТЫ УЧЕТ НОЙ ИНФОРМАЦИИ Учетная информация по учебному процессу может быть представлена в планах проведения занятий в группах на текущий семестр, содержащих перечень изучаемых предметов с часами лекционных и практических занятий (см. рис. 3). Из этого документа можно почерпнуть сведения об объекте ПРЕДМЕТ и процессе ИЗУЧЕНИЕ. Как мы увидим далее процессы будут представлены многомногозначными связями, предс тавленными информационными объектами (или реляционными таблицами в БД).
План проведения занятий в группе
Рис. 3.
Форма документа с перечнем предметов по видам занятий
Эта таблица дает нам сведения о том, какие предметы изучает каждая группа, какой преподаватель ведет те или иные занятия, о характере занятий (лекции, практические занятия или лабораторные работы), о количестве часов, отведенных на каждый предмет по каждому виду занятия. Сведения об итоговых результатах по учебному процессу за семестр представляются в заполненных экзаменационных ведомостях (см. рис. 4).
Экзаменационная ведомость
Рис. 4.
Форма бланка экзаменационной ведомости
—9— Здесь представлены сведения об успеваемости студента или информационном объекте УСПЕВАЕМОСТЬ, который также описывает многомногозначную связь, т.е. процесс. 1.2. ПОСТРОЕНИЕ ЛОГИЧЕСКОЙ МОДЕЛИ ДАННЫХ Логическая (или концептуальная) модель отображает данные ПрдО в виде совокупности информационных объектов и связей между ними. Эта модель представляет данные, подлежащие хранению в БД. 1.2.1. ИНФОРМАЦИОННЫЕ ОБЪЕКТЫ Информационный объект - это описание некоторой сущности ПрдО - реального объекта, процесса, явления или события. Информационный объект образуется совокупностью логически взаимосвязанных реквизитов, представляющих качественные и количественные характеристики сущности. Реквизит смысловая структурная единица, которая не расчленяется в процессе обработки. Реквизит является совокупностью двух элементов: наименования и значения. В реляционной БД реквизит моделируется полем таблицы. Процесс выделения информационных объектов ПрдО может производиться на основе интуитивного или формального подхода. При интуитивном подходе легко могут быть выявлены информационные объекты, соответствующие реальным объектам. Но получаемая при этом логическая модель, как правило, требует дальнейших преобразований. Порядок выделения информационных объектов. Рассмотрим формальные правила, которые могут быть использованы для выделения информационных объектов, отвечающих требованиям нормализации: • на основе описания ПрдО выявить документы и их реквизиты, подлежащие хранению в БД; • определить функциональные зависимости между реквизитами; • выбрать все зависимые реквизиты и указать для каждого все его ключевые реквизиты, т. е. те, от которых он зависит; •- сгруппировать реквизиты, одинаково зависимые от ключевых реквизитов, которые и образуют информационные объекты. Определим функциональные зависимости между реквизитами документа «Список преподавателей кафедры», предварительно включив их перечень в таблицу. Из анализа документа очевидно, что реквизиты «Название кафедры» (НКАФ), «Телефон» (ТЕЛ), «Заведующий» (ЗАВ) являются описательными и каждый из них зависит только от ключевого реквизита «Код кафедры» (ККАФ), который в то же время выполняет роль общего идентификатора списка преподавателей кафедры. Реквизиты «Фамилия И.О.» (ФИО), «Уч. степень» (СТ), «Уч. звание» (зв) однозначно определяются ключевым реквизитом «Таб. номер» (ТАБН) преподавателя.
- 10Обратим внимание на связь реквизитов ККАФ и Т АБН. В этой функциональной зависимости выполняется необходимое условие - одному значению ключа Т АБН соответствует одно значение зависимого реквизита ККАФ, так как преподаватель числится на конкретной кафедре. Таким образом, реквизит ККАФ играет роль описательного реквизита для преподавателя с идентификатором Т АБН. Заметим, если такая связь не выявлена, то все множество реквизитов документа разделится на два несвязанных между собой подмножес тва, а это нелогично для реквизитов одного документа. Все установленные функциональные зависимости реквизитов документа «Список преподавателей кафедры» отражены на рис. 5.
Рис. 5. Функциональные зависимости реквизитов
Реквизит ККАФ одновременно выступает в роли описательного реквизита
в одной связи и ключевого - в другой связи. Таким образом, здесь мы сталкиваемся с транзитивной зависимостью. Реквизит НКАФ транзитивно зависит от ТАБН через ККАФ. Тем не менее, специальных действий по расщеплению этой связи не потребуется: Выберем по функциональным связям реквизиты, зависимые от какихлибо других реквизитов и укажем для них ключевые реквизиты. Так, при просмотре списка реквизитов сверху находим первый зависимый (описательный) реквизит ККАФ и устанавливаем реквизит, от которого идет стрелка — ТАБН. Далее находим второй зависимый (описательный) реквизит НКАФ и устанавливаем его ключевой ККАФ и так далее. Соответствие описательных и ключевых реквизитов представлено в табл. 1.
Сгруппируем реквизиты, зависимые от одних и тех же ключевых реквизитов, и объединим их с ключевыми реквизитами в один информационный объект. Результат группировки реквизитов документа «Список преподавателей кафедры» приведен в табл. 2. Таким образом, на основе анализа документа «Список преподавателей кафедры» выделены два информационных объекта: КАФЕДРА И ПРЕПОДАВАТЕЛЬ.
11Табл. 1.
Соответствие реквизитов
Табл. 2.
Группировка реквизитов по информационным объектам
Если функциональная зависимость реквизитов ККАФ и Т АБН не была бы выявлена на с тадии анализа (см. рис. 5), реквизит ККАФ пришлось бы добавить в объект ПРЕПОДАВАТ ЕЛЬ для обеспечения связей объектов в реляционной базе (следует заметить, что современные CASE-средства реализуют такое добавление автоматически при установлении связи между информационными объектами). Аналогично рассмотренному выше может быть выполнен анализ документа «Список студентов группы» и будут выявлены другие объекты справочной информации: ГРУППА, СТ УДЕНТ . Объект ГРУППА характеризуется числом студентов в группе, средним проходным баллом. Для однозначной идентификации группы используется ее номер. Объект СТ УДЕНТ имеет описательные реквизиты: фамилию с инициалами, год рождения, адрес проживания. Для идентификации с тудента можно использовать его порядковый номер в списке группы. Тогда для уникальной идентификации среди всех студентов вуза можно использовать составной ключ из номера группы и порядкового номера в группе. Такой идентификатор позволяет в то же время определить принадлежнос ть студента к группе. К объектам справочной информации относится также информационный объект ПРЕДМЕТ, который легко выявляется на основе интуитивного подхода. Объект ПРЕДМЕТ характеризуется наименованием, общим количеством часов, количеством часов лекций, практических занятий, числом семестров и т. п., в качестве идентификатора предмета вместо наименования целесообразно взять уникальный код предмета. Это облегчит реализацию в БД связей этого объекта
-12с другими, в которых необходима ссылка на предмет. Описанные объекты представлены в табл. 3. Документ «План проведения занятий в группе» (см. рис. 3) содержит сведения о занятиях, проводимых в каждой группе в текущем семестре. Часы – это основная количественная характеристика занятия, т. е. описательный реквизит. Соответственно, он является реквизитом, зависимым от идентификаторов занятия: номера группы, кода изучаемого предмета, идентификатора преподавателя и вида занятий, поскольку учет ведется отдельно по лекциям и практическим занятиям. Кроме того, к описательным реквизитам можно отнести расчетный реквизит - среднюю оценку в группе по занятию, если его хранить в БД. Табл. 3. Объекты ГРУППА, СТУДЕНТ и ПРЕДМЕТ Объект
Название реквизита
ГРУППА
Номер группы Количество студентов Средний балл Номер группы Номер студента Фамилия И.О. Год рождения Адрес Балл при поступлении Код предмета Название предмета Всего часов Часов лекций Часов практики Число семестров Программа курса
СТУДЕНТ
ПРЕДМЕТ
Обозначение Признак реквизита ключа НГ Уникальный, КОЛ простой ПБАЛЛ НГ Уникальный, НС составной ФИО ГОДР АДРЕС ПБАЛЛ _ КП У НП простой й ЧАСЫ ЛЕК ПР i ЧС ПРОГ
В результате анализа взаимосвязей реквизитов этого документа можно выделить новый информационный объект ИЗУЧЕНИЕ. На основе анализа документа «Экзаменационная ведомость» может быть выделен другой объект учетной информации - УСПЕВАЕМОСТЬ. Полный состав объектов учетной информации представлен в табл. 4. Объект УСПЕВАЕМОСТЬ обеспечивает хранение в БД информации об итоговых оценках студента за семестр по каждому виду занятия, отображенному в объекте ИЗУЧЕНИЕ. Соответственно, такая оценка определяется, с одной стороны, идентификатором студента («Номер группы» + «номер студента») , а с другой стороны - идентификатором занятия («Номер группы» + «Код предмета» + «Таб. номер преподавателя» + «Вид занятия») . Таким образом, их объединение образует уникальный идентификатор объекта УСПЕВАЕМОСТЬ.
- 13Табл. 4.
Объекты учетной информации
Объект
Название реквизита
ИЗУЧЕНИЕ
Номер группы Код предмета
УСПЕВАЕМОСТЬ
Таб. номер преподавателя Вид занятия Часы занятия Средний балл группы Номер группы Номер студента Код предмета Таб. номер преподавателя Вид занятия Оценка
Обозначение Признак реквизита ключа нг ! Уникальный, КП составной ТАБН
ВИДЗ
ЧАСЫ СБАЛЛ-ГР НГ Уникальный, НС составной КП
ТАБН
видз
ОЦЕНКА
1.2.2. СВЯЗИ ИНФОРМАЦИОННЫХ ОБЪЕКТОВ Следующим шагом проектирования после выявления информационных объектов является определение связей между ними. Связь устанавливается между двумя информационными объектами. Наличие связи, как правило, определяется природой реальных объектов, процессов или явлений, отображаемых этими информационными объектами. Связи между объектами существуют, если логически взаимосвязаны экземпляры из этих информационных объектов. Например, связи между такими парами объектов, как кафедра-преподаватель, группа-студент и т. п. Связи между объектами ГРУППА → СТУДЕНТ характеризуются одномногозначными отношениями, поскольку одна группа включает много студентов, а один студент входит только в одну группу. Связь между ним и осуществляется по номеру группы, который является уникальным идентификатором главного объекта ГРУППА и входит в составной идентификатор объекта СТУДЕНТ (см. табл. 3). Аналогично устанавливается связь между объектами КАФЕДРА → ПРЕПОДАВАТЕЛЬ, которые также находятся в одно-многозначных отношениях. Связь между ними осуществляется по уникальному ключу главного объекта КАФЕДРА - коду кафедры, который в подчиненном объекте ПРЕПОДАВАТЕЛЬ является описательным (см. табл. 2). В каждой группе в течение семестра проводятся ряд видов занятий (объект ИЗУЧЕНИЕ) в соответствии с изучаемыми предметами. С другой стороны, каждый вид занятия определен для конкретной группы. Поэтому имеет место связь типа один-ко-многим между объектами ГРУППА→ИЗУЧЕНИЕ.
- 14Табл. 5.
Связи информационных объектов
По каждому предмету проводится множество занятий в разных группах разными преподавателями. С другой стороны, каждое занятие проводится по конкретному предмету, что определяет отношения типа одинко-многим между объектами ПРЕДМЕТ → ИЗУЧЕНИЕ. Аналогично определяются отношения типа один-ко-многим между объектами ПРЕПОДАВАТ ЕЛЬ → ИЗУЧЕНИЕ. Следует отметить, ч то объект ИЗУЧЕНИЕ фактически играет роль объекта связки в много-многозначных отношениях между объектами ГРУППА → ПРЕД МЕТ, ГРУППА → ПРЕПОДАВАТЕЛЬ, ПРЕДМЕТ → ПРЕПОДАВАТЕЛЬ (см. рис. 6).
Объект УСПЕВАЕМОСТЬ содержит данные об успеваемости (оценку) конкретного студента по конкретному виду занятия. Поэтому он является связанным с объектом СТ УДЕНТ и объектом ИЗУЧЕНИЕ. Один студент имеет данные по нескольким предметам, но эти данные всегда относятся к одному конкретному студенту. Это означает, что объект У СПЕВАЕМОСТЬ является подчиненным и находится в одно-многозначных отношениях с объектом СТ УДЕНТ. Объект У СПЕВАЕМОСТЬ является также подчиненным и находится в одно-многозначных отношениях с объектом ИЗУЧЕНИЕ, так как по одному виду занятия имеется множество данных об успеваемости разных студентов, но каждое из них всегда определено по конкретному занятию. Заметим, что объект УСПЕВАЕМОСТ Ь выполняет роль объекта-связки в много-многозначных отношениях объектов СТ УДЕНТ и ИЗУЧЕНИЕ. Многомногозначные отношения между этими объектами определяются тем, что одному студенту соответс твует много видов занятий, отображаемых объектом ИЗУЧЕНИЕ, а один вид занятия проводится со многими студентами. В табл. 5 перечислены все одно-многозначные связи между объектами, указаны ключи, по которым должны устанавливаться связи, и определены главные и подчиненные информационные объекты в этих связях.
- 151.2.3. ИНФОРМАЦИОННО-ЛОГИЧЕСКАЯ МОДЕЛЬ ПРДО На рис. 7 представлена информационно-логическая модель рассматриваемой ПрдО, построенная в соответствии с выявленными информационными объектами и связями между ними. Информационнологическая модель приведена в каноническом виде, так как объекты размещены по уровням. На нулевом уровне размещаются объекты, не подчиненные никаким другим объектам. Уровень остальных объектов определяется наибольшей длиной пути (количеством связей) к объекту от объекта нулевого уровня. Такое размещение объектов дает представление об их иерархической подчиненности, делает модель более наглядной и облегчает понимание одномногозначных отношений между объектами. По полученной модели далее строится логическая модель ПрдО, которая описывается в следующем разделе.. 1.2.4. ЛОГИЧЕСКАЯ СТРУКТУРА РЕЛЯЦИОННОЙ БД Логическая структура реляционной БД является адекватным отображением полученной информационно-логической модели, не требующим дополнительных преобразований. Каждый информационный объект модели данных отображается соответствующей реляционной таблицей. Структура реляционной таблицы определяется реквизитным составом соответствующего информации онного объекта, где каждый столбец (поле) соответствует одному из реквизитов объекта. Ключевые реквизиты объекта образуют уникальный ключ реляционной таблицы. Для каждого столбца задается формат и размер данных, т. е. определяется либо тип данных, поддерживаемый СУБД, либо домен, базирующийся на одном из типов данных. Строки (записи) таблицы соответствуют экземплярам объекта и формируются при загрузке таблицы. Связи между объектами модели данных реализуются одинаковыми рекви зитами - ключами связи в соответствующих таблицах. При этом ключом связи
- 16всегда является уникальный ключ главной таблицы. Ключом связи в подчиненной таблице является либо некоторая часть уникального ключа в ней, либо поле, не входящее в состав первичного ключа (например, код кафедры в таблице ПРЕПОДАВАТ ЕЛЬ). Ключ связи в подчиненной таблице называется внешним (или вторичным) ключом.
Рис. 8. Логическая структура реляционной БД ПрдО «Учебный процесс»
На рис. 8 приведена схема данных, наглядно отображающая логическую структуру БД. На этой схеме прямоугольники отображают таблицы БД с полным списком их полей, а связи показывают, по каким полям осуществляется взаимосвязь таблиц. Имена ключевых полей для нагляднос ти выделены и находятся в верхней части полного списка полей каждой таблицы.
- 17-
ГЛАВА 2. ПРОЕКТИРОВАНИЕ БД С ПОМОЩЬЮ ПРОГРАММЫ ERWIN Логическая модель является основой разработки физической модели БД, которая хранится в памяти машины. Из-за возрастающей сложности моделируемых систем возрастает и вероятнос ть ошибок при разработке логических моделей, которые, в отличие от концептуальных моделей, более конкретны. Стоимость таких ошибок весьма высока, так как исправление ошибок, допущенных на предыдущих этапах разработки системы, в десятки раз дороже, чем исправление ошибки, появившейся на текущей стадии. Еще одна проблема разработки сложных систем - это время разработки, которое сравнимо с предполагаемым временем эксплуатации таких систем, поэтому сокращение времени разработки становится одной из важных задач ее организации. В связи с вышесказанным огромное значение приобрели средства автоматизированного проектирования ИнфС - так называемые CASE-средства (ОТ английского Computer Aided Software/System Engineering). CASEсредства основаны на том принципе, что ПрдО разработки описывается в виде формальной модели, на основе которой генерируется код приложения. В настоящее время имеется множество средств автоматизации разработки, они предназначены как для разработки БД, так и для разработки клиентских приложений. В следующей главе мы рассмотрим одну из самых распространенных программ - ERwin фирмы PLAT INUM. Эта программа позволяет не только спроектировать, но и создать БД на сервере.
2.1. СОЗДАНИЕ ЛОГИЧЕСКОЙ МОДЕЛИ БД Создание реляционной БД с помощью. ERwin начинается с введения в диаграмму сущностей, определенных на логической схеме. Определив сущности, необходимо ввести в схему и атрибуты этих сущностей. Каждый из атрибутов связывают с определенным типом данных. Но на практике удобнее определить домены - подмножества типов данных, более точно описывающих атрибуты. Поэтому, прежде чем приписать введенные атрибуты к сущностям, определяются домены. Задав атрибуты сущностей, мы определяем таблицы БД, соответствующие сущностям ПрдО. На последнем этапе определяем связи между введенными таблицами. 2.1.1. СОЗДАНИЕ СУЩНОСТЕЙ Для построения логической модели, прежде всего, необходимо определить набор сущностей предметной облас ти и задать связи между ними. Перейдите на закладку «Уровень сущностей».
- 18Проектирование БД с помощью CASEсредства ERwin проведем на примере предметной облас ти, относящейся к материальному обеспечению процесса обучения и содержащей следующие сущности: • Студент — содержит список студентов, обучающихся на кафедре; •- Группа - СПИСОК групп студентов, выпускаемых кафедрой; • Преподаватель — список преподавателей, работающих на кафедре; • Кафедра кафедр;
-
СПИСОК
•- Предмет - список предметов, изучаемых студентами; •- Изучение - сведения о том, какие студенты какие предметы изучают и какой преподаватель ведет занятия; •- Успеваемость - сведения о результатах изучения предметов студентами. Выделите в палитре инструментов кнопку сущности. Затем щелкните по чистой облас ти диаграммы, и на поле появится прямоугольник, изображающий новую сущность с именем «Е/1». Измените его на «Студент», введя это имя с клавиатуры. Таким же образом вставьте в диаграмму еще шес ть сущностей «Группа», «Преподаватель», «Кафедра», «Предмет», «Изучение» И «Успеваемость». Каждая из сущностей, как и всякий объект ER-диаграммы, обладае т контекстным меню, для вызова которого необходимо щелкнуть по прямоугольнику сущности правой кнопкой мыши. Выберите пункт меню Entity Editor... для вызова редактора сущности, позволяющего изменять свойства выбранной сущности. В верхней час ти окна редактора сущностей (рис. 9) находится список всех сущностей диаграммы. Далее имеется поле Name, в котором высвечивается имя сущности, которое может редактироваться. Ниже в окне редактора находится ряд закладок: •- Definition - на этой странице вводится определение сущности;
- 19•- Note, Note2, Note3 - используются для ввода произвольного текста, связанного с сущностью; •- UDP - на этой странице пользователь может определить свои свойства; • icon — для наглядности каждой сущности может быть присвоена иконка, которая выводится рядом с ее названием. 2.1.2. СОЗДАНИЕ ДОМЕНОВ Определив сущности, необходимо внести в схему и атрибуты этих сущностей. Перечень сущностей и их атрибутов приведен в табл. 6. Как мы уже отметили, атрибуты сущности при преобразовании логической схемы в физическую схему базы данных становятся колонками таблицы, в которых хранятся значения определенных типов данных. ERwin позволяет указать этот тип данных на диаграмме, однако, удобнее определять тип данных атрибута не через простой тип данных, а через его подмножество-домен, который более тонко классифицирует свойства сущностей.
Для создания доменов служит диалог Domain Dictionary Editor. Его можно вызвать из меню «Edit\Domain Dictionary...». В ответ на экране появляется диалоговое окно (см. рис. 10), которое позволяет создавать и редактировать домены в двух режимах - логическом и физическом. Переключение режима производится при помощи списка с меткой «Edit Mode».
-20Табл. 6. Сущности предметной области и их атрибуты
-21Внизу находится список доменов, содержащий пять базовых доменов, на основе которых разработчик может определить собственные домены: •- String (СТРОКОВЫЙ); • Number (числовой); •- DateTime (время);
•- Blob (двоичный). В нижней части слева находятся кнопки: •- New - создание нового домена; •- Rename - переименование домена; •- Delete - удаление домена; •- Reset-сброс свойств домена. В правой части расположены страницы с закладками, позволяющими редактировать свойства доменов. В логическом режиме имеется четыре страницы: General, Definition, Note, UDP. На странице General редактируются ненаследуемые и наследуемые свойства. Ненаследуемые свойства относятся только к домену и не передаются атрибутам, определенным на базе этого домена. К ним относятся родительский домен (Domain parent) и иконка домена (Domain icon). Наследуемые свойства передаются всем атрибутам, созданным на базе домена. К этим свойствам относятся наследуемое имя и иконка. В качестве наследуемого имени по умолчанию устанавливается % AttDomain макроопределение, которое заменяется на имя домена. Это означает, что при создании атрибута на базе данного домена его логическим именем будет имя домена. Кроме того, при помощи флажков, находящихся в нижней части страницы General, вы можете задать: •- Required - атрибут, созданный на базе домена, является обязательным. В физической модели это соответст вует заданию для поля опции NOT NULL.
•- Logical - домен должен быть виден только в логической модели. Страницы Definition, Note, UDP не отличаются отаналогичных страниц, описанных для других объектов диаграммы.
22
Для создания нового домена в диалоге Domain Dictionary Editor нажмите на кнопку New и в появившемся диалоговом окне (рис. 11): •- выберите родительский домен Number из списка Domain Parent; •- наберите имя домена «код класса» в поле «Logical Name»; •- в поле «Physical Name» введите физическое имя домена «t_student_id». Физическое имя станет именем типа данных в таблице БД.
По умолчанию ERwin генерирует физическое имя из логического, заменяя пробелы символом подчеркивания «_». В нашем случае он создал имя «код студента», но так как сервера не поддерживают имен, содержащих символы кириллицы, мы заменили его на английское имя «t_student_id». Префикс «t_» означает, что это имя типа данных (домена). Нажмите кнопку OK и новый домен будет добавлен в список.
- 23 генерируемых в запросах CREATE TABLE будут использованы домены. Если этот флажок не установлен, то программа вместо доменов проставит базовые типы данных. В поле «Name inherited By Column» вводится макропрограммирование, генерирующее имя колонки, которая создается на базе этого домена. ERwin содержит встроенную систему макроопределений, с помощью которых можно существенно изменить и настроить поведение программы в различных ситуациях. В данном случае используется макрос %ColDomain, возвращающий физическое имя домена, т.е. программа будет генерировать имя колонки, совпадающее с именем домена. Но в нашем случае желательно несколько видоизменить это название, так как имя домена начинается с префикса «t_», и мы не хотим, чтобы этот префикс попал в имя колонки. Для этого воспользуемся макросом %Substr (), синтаксис которого имеет вид %Substr(<строка>, <начальная позиция>,<длина>).
Введите в поле наследуемого имени макроса %Substr (%ColDomain, 3, 50), согласно которому имя колонки будет генерироваться равным имени домена, но начиная с третьего символа. Число 50 обозначает длину символа.
Рис.13. Страница «InterBase»
Следующая страница зависит от заданного типа сервера, для которого будет генерироваться БД. В нашем случае выбран сервер InterBase (см. рис. 13). Для выбранного в списке домена здесь выбираются: • InterBase Datatype - физический тип данных, определенный для сервера InterBase. В этом же поле проставляется размерность; • Null Option позволяет задать домены, у которых должно быть предопределено СВОЙСТВО NOT NULL ИЛИ NULL;
24Табл. 7. Домены, используемые в разрабатываемой БД ЛОГИЧЕСКОЕ ИМЯ ДОМЕНА Номер группы Номер студента Фамилия И.О. Год рождения Адрес Количество студентов Балл Код предмета Название предмета Количество часов Число семестров Программа курса Таб. номер Уч. степень Уч. звание Код кафедры Название кафедры Телефон Вид занятия Оценка
ТИП ДОМЕНА Number String String Date String Number Number Number String Number Number String Number String String Number String String String Number
i
• Поля со списком задают правила валидации (проверки допустимого значения); • Страница Comment. Внесение комментария к атрибуту; • Страница UDP. Свойства, определяемые пользователем; Таким же образом создайте остальные домены, имена и базовые типы которых приведены в табл. 7. 2.1.3. УСТАНОВКА АТРИБУТОВ СУЩНОСТИ Теперь у нас есть все необходимые домены для задания сущностей на диаграмме. Определим сначала сущность «СТУДЕНТ ». Для этого в палитре инструментов выберите кнопку «стрелка», выделите сущность «СТУДЕНТ », щелкнув по нему указателем мыши, а затем вызовите «Edit\Attribute...». Этот же результат можно получить, выбрав пункт «Attribute Editor...» контекстного меню. При этом на экране появится окно редактора атрибутов (рис. 14). Структура редактора атрибутов аналогична структуре редактора сущностей.
-25В верхней части находится выпадающий список, в котором можно выбрать сущность для редактирования. Рядом имеется кнопка, с помощью которой можно вызвать редактор сущностей. Для ввода нового атрибута нажмите «NEW » и выберите в списке доменов домен «код класса» (рис. 15). Макроопределения, которые мы задали для наследуемых имен домена (%AttDomain и %Substr (%ColDomain, 3,50) ), генерируют в поле «Attribute Name» имя атрибута «код класса», а в поле «Column Name» —«class id».
Рис. 14. Редактор атрибутов
После нажатия кнопки ОК атрибут появится в окне редактора. Таким же образом введите остальные атрибуты сущности «Класс». Затем выделите атрибут «код класса» и установите флажок «Primary Key». Так мы назначаем атрибут «код класса» первичным ключом сущности «Класс». Порядок следования атрибутов можно менять при помощи кнопок со стрелками (рис. 14). До сих пор мы работали на уровне сущностей, где сущности изображались просто прямоугольниками с названием сущности внутри. А теперь перейдем на вкладку «Уровень атрибутов». Здесь сущности также изображаются в виде прямоугольников, однако, имя сущности пишется над прямоугольником, а внутри него дается список атрибутов. Аналогично определим атрибуты остальных сущностей на диаграмме. Сущности можно определять и другим способом, а именно с помощью специального инструмента «Independent Attribute Browser», который вызывается или нажатием CTRL+B, ИЛИ Window\Independent Attribute Browser.
-26-
Рис. 15. Создание атрибута
Рис. 16. Окно браузера атрибутов
Вызовите браузер на экран (см. рис. 16). Преимущество браузера заключается в том, что он позволяет задавать атрибуты сущности простым перетаскиванием. Для этого достаточно выделить нужное имя домена в списке, нажать левую кнопку мыши и, не отпуская ее, перенести указатель в прямоугольник сущности. Когда вы отпус тите кнопку мыши, программа создаст атрибут от выбранного домена.
Рис. 17. Сущности объектной области «Учебный процесс»
- 27После определения всех сущностей нашей предметной облас ти диаграмма будет иметь вид, показанный на рис. 17. На данной диаграмме отсутс твуют некоторые ключевые поля, отраженные на информационно-логической модели и логической структуре БД «Учебный процесс». Эти поля участвуют в создании связей между сущностями и будут введены автоматически после установления связей. 2.1.4. УСТАНОВКА СВЯЗЕЙ МЕЖДУ СУЩНОСТЯМИ После того как определены все сущности, необходимо задать связи между ними. Связь в ERwin трактуется как функциональная зависимость между двумя сущностями. Если рассматривать диаграмму как графическое изображение предметной области, то сущности являются существительными, а связи - глаголами. Например, между сущностями « ГРУППА» и «СТ УДЕНТ » имеет мес то связь «состоит из» (см. рис. 18). В ERwin связи представлены пятью основными элементами информации: •- Тип связи. ERwin поддерживает следующие основные типы связей: • идентифицирующая, если экземпляр дочерней сущности идентифицируется через связь с ее родительской сущностью. Атрибуты, составляющие первичный ключ родительской сущности, входят в первичный ключ дочерней сущности. Идентифицирующая связь изображается сплошной линией; Рис. 18. Неидентифици> неидентифицирующая, если экземпляр дочерней рующая связь сущности идентифицируется иначе, чем через связь с родительской сущностью. Атрибуты, составляющие первичный ключ родительской сущности, при этом входят в состав неключевых атрибутов дочерней сущности. Неидентифицирующая связь изображается пунктирной линией; > категорийная связь используется, когда некоторая сущность определяет целую категорию объектов одного типа. В таком случае создается сущность для определения категории и для каждого элемента категории, а затем вводится для них связь категоризации. Родительская сущность называется супертипом, а дочерняя подтипом. Общая часть атрибутов сущностей-подтипов, включая первичный ключ, помещается в сущность-супертип. Различающаяся часть помещается в сущностях-подтипах. В сущности-супертипе вводится атрибут дискриминатор, позволяющий различать конкретные экземпляры сущности подтипа. В зависимости от того, все ли возможные сущности-подтипы включены в модель, категорийная связь является полной или неполной; > многие-ко-многим - ситуация, когда одной сущности соответс твует один или несколько экземпляров второй сущности, а экземпляру второй
-28сущности соответствует один или несколько экземпляров первой сущности, отражается логической моделью «многие-ко-многим» между данными сущностями. Связь данного типа возможна только на логическом уровне. На физическом уровне связь этого типа заменяется сущностью. • Родительская и дочерняя (зависимая) сущности. Дочерняя сущность при идентифицирующей связи всегда является зависимой. • Мощность связи - представляет собой отношение количества экземпляров родительской сущности к соответс твующему количес тву экземпляров дочерней сущности. Мощность связи определяется только для идентифицирующих и неидентифицирующих связей. • Допустимос ть пус тых (null) значений в неидентифицирующих связях ERwin изображает пус тым ромбиком на дуге связи со стороны родительской сущности.
• Требования по обеспечению ссылочной целостности. Под ссылочной целостностью понимается обеспечение требования, чтобы значения внешнего ключа экземпляра дочерней сущности соответствовали значениям первичного ключа родительской сущности. Для каждой связи могут быть заданы требования по обработке операций INSERT /UPDATE/DELETE для родительской и дочерней сущности. ERwin предоставляет следующие варианты обработки этих событий: > отсутствие проверки (NONE); > проверка допустимости (SET NULL); > запрет операции (RESTRICT ); > каскадное выполнение операции DELETE/UPDATE (CASCADE); > установка пустого (NULL-значения) или заданного значения по умолчанию (SET DEFAULT ). Следует отметить еще одно обстоятельство. Поскольку атрибуты первичного ключа родительской сущности по умолчанию мигрируют со своими именами, ERwin считает, что в зависимой сущности атрибуты внешнего ключа появляются только один раз. Чтобы избежать этого ограничения, ERwin позволяет ввести для них роли, т. е. новые имена, под которыми мигрирующие имена будут представлены в дочерней сущности. В случае неоднократной миграции такое переименование необходимо. Наша диаграмма содержит семь сущностей. Определим связи между ними. Вернитесь на вкладку «Уровень сущностей». Мы задали для студента собственный уникальный ключ «Номер студента». Следовательно, сущность «СТУДЕНТ » является независимой сущностью и связана с сущностью «ГРУППА» неидентифицирующей связью. Для того чтобы проставить эту связь на диаграмме, щелкните указателем мыши по кнопке «Nonldentifying Relationship» в палитре инструментов, затем щелкните по очереди по прямоугольникам сущностей «ГРУППА» и «СТУДЕНТ » на диаграмме. Между этими сущностями появится пунктирная линия неидентифицирующей связи. Посреди линии связи проставляется генерируемая по умолчанию глагольная фраза - «R/1» (см. рис. 18).
-29Перейдя на уровень атрибутов, вы можете обнаружить, что у сущности «СТ УДЕНТ» добавился атрибут первичного ключа от сущности «ГРУППА» и помечен буквами «FK» (см. рис. 19). Для идентифицирующей связи внешний ключ всегда входит в первичный ключ дочерней сущности, для неидентифицирующей - не входит. Связи на диаграмме лучше Рис. 19. Миграция атрибутов воспринимаются, если им присваиваются глагольные фразы. Это можно сделать с помощью редактора связей. Для его вызова щелкните по связи указателем мыши, затем нажмите правую кнопку мыши и в контекстном меню выберите «Relationship Editor...» (рис. 20). Редактор связей похож на остальные редакторы объектов ERдиаграммы. В верхней части находится выпадающий список с названием связи. В нашем случае осмысленная фраза еще не определена, поэтому в этом поле значится «Группа R/1 Студент». С помощью кнопок New... и Delete можно добавить новую связь или удалить существующую.
Рис. 20. Окно редактора связей
-30-
В редакторе имеется четыре страницы: • General - на этой странице задаются основные свойства связи - глагольная фраза, тип и степень связи. > Verb Phrase содержит два поля, в которых вводится глагольная фраза, характеризующая связь. Можно задать фразу для прямого (Parent-To-Child) и обратного (Child-To-Parent) направления связи. Щелкните указателем мыши по полю Parent-To-Child и введите «состоит из». > Cardinality позволяет выбрать одну из следующих степеней связи: - «Zero One or More» — каждый экземпляр родительской сущности связан с нулем, одним или более экземпляров дочерней сущности; - «One or More (P)» - каждый экземпляр родительской сущности связан с одним или более экземпляров дочерней сущности; - «Zero or One (z)» — каждый экземпляр родительской сущности связан с нулем или одним экземпляром дочерней сущности; - «Exactly» - каждый экземпляр родительской сущности связан с заданным количеством экземпляров дочерней сущности. Рядом находится поле, где необходимо ввести это поле.
-31> Relationship Type - связь может быть идентифицирующей и неидентифицирующей. Кроме того, для неидентифицирующей связь может быть либо обязательной, либо необязательной. Например, при анализе предметной области мы выяснили, что учебное место не может существовать отдельно от класса. Поэтому установите переключатель Nulls в позицию «No nulls». Тем самым на отношение накладывается условие, что у существующего экземпляра учебного места всегда должна быть ссылка на класс, в который оно входит. • Definition - на этой странице вводится определение связи. • Rolename/Rl Action (имя роли/установка ссылочной целостности). Имя роли - это дополнительная характерис тика, которая присваивается мигрирующему атрибуту первичного ключа (рис. 21), в тех случаях, когда сущность связана со многими сущностями или сама с собой циклической связью. Установка ссылочной целостнос ти - это логические конструкции, которые выражают ограничения использования данных. Они определяют, какие дейс твия должна выполнять СУБД при удалении, вставке или изменении с троки таблицы (экземпляра сущности). Заданные таким образом действия могут использоваться впоследствии при автоматической генерации триггеров, поддерживающих целостность данных. Существуют следующие виды дейс твий или правил, определенных в логической модели: •- REST RICT - запрет удаления, вставки или изменения экземпляра сущности. • CASCADE — при удалении родительской сущности удаляются все экземпляры дочерней сущности, ссылающиеся на удаляемый экземпляр. • SET NULL - при удалении экземпляра родительской сущности атрибутам внешнего ключа всех экземпляров дочерней сущности присваивается значение NULL.
• SET DEFAULT - то же самое, только вместо умолчанию.
NULL
присваивается значение по
-32• NONE - никаких действий не принимается. При добавлении связи в диаграмму ERwin по умолчанию ус танавливает набор правил, которые можно редактировать в диалоге «Referential Integrity Defaults Editor», вызывающемся из диалогового окна «Target Server» нажатием «RI Defaults» (рис. 22). При нажатии на «Rebind» (переназначить) новые установки умолчаний переносятся в текущую модель, если же прос то выйти из диалога, то измененные установки влияют только на новые модели. Табл. 8. Набор допустимых правил для различных типов связей Наименование действия (операции) Child Delete (Удаление дочернего объекта)
ТИП СВЯЗИ ИДЕНТИФИЦИРУЮЩАЯ
RELATIONSHIP НЕИДЕНТИФИЦИРУЮЩАЯ
ТЕ) НЕИДЕНТИФИЦИРУЮЩАЯ
RESTRICT CASCADE NONE
RESTRICT CASCADE NONE
RESTRICT RESTRICT CASCADE CASCADE NONE NONE SET NULL SET DEFAULT SET DEFAULT RESTRICT RESTRICT CASCADE CASCADE NONE NONE SET NULL SETDEFAULT SET DEFAULT RESTRICT RESTRICT CASCADE CASCADE NONE NONE SET NULL SET DEFAULT SET DEFAULT
Child Insert (Вставка дочернего объекта)
RESTRICT CASCADE NONE
RESTRICT CASCADE NONE
Child Update (Изменение дочернего объекта)
RESTRICT CASCADE NONE
RESTRICT CASCADE NONE
Parent Delete (Удаление родительского объекта)
RESTRICT CASCADE NONE
RESTRICT CASCADE NONE
Parent Insert (Вставка родительского объекта)
RESTRICT CASCADE NONE
RESTRICT CASCADE NONE
Parent Update (Изменение родительского объекта)
RESTRICT CASCADE NONE
RESTRICT CASCADE NONE .
КАТЕГОРИАЛЬНАЯ СВЯЗЬ
RESTRICT RESTRICT CASCADE CASCADE NONE NONE SET DEFAULT SET NULL SET_DEFAULT RESTRICT RESTRICT CASCADE CASCADE NONE NONE SET NULL SET DEFAULT SET DEFAULT RESTRICT RESTRICT CASCADE CASCADE NONE NONE SET NULL SET DEFAULT SET DEFAULT
Наборы допустимых правил для каждого типа связи в зависимости от вида действия приведены в табл. 8. Например, установки для связи «Группа - Студент», присвоенные по умолчанию, запрещают вставку и изменение экземпляра дочерней сущности, а также удаление и изменение родительской сущности.
-33-
Это означает, что не допускается удаление или изменение класса, если в нем имеются учебные мес та, а также ввод учебного места без указания класса или со ссылкой на соответствующий класс. • UDP позволяет присвоить связи свой набор пользовательских свойств. Итак, мы создали неидентифицирующую связь между сущностями «ГРУППА» и «СТ УДЕНТ » с условием «NO Nulls». Между сущностями «КАФЕДРА» и «ПРЕПОДАВАТ ЕЛЬ » имеет место связь того же типа, так как преподаватель может существовать отдельно от кафедры и имеет свой идентификационный код «Табельный номер». Внесите эту связь в диаграмму, как мы это описали выше, выбрав сущность « КАФЕДРА» в качестве родительской, а «ПРЕПОДАВАТ ЕЛЬ » - дочерней. Вызовите редактор связей и измените глагольную фразу на «состоит из», остальные установки связи оставьте неизменными. При этом атрибут «код кафедры» мигрирует в состав неключевых атрибутов сущности «ПРЕПОДАВАТЕЛЬ ».
Рис. 23. ER-диаграмма после установки связей
После установки всех связей диаграмма на уровне сущностей будет иметь вид, показанный на рис. 23. На диаграмме графическое изображение связи зависит от типа. Графическое изображение зависит еще и от принятой методологии построения диаграммы. Например, в нотации IDEFIX, используемой в этом примере, принято изображение связей, показанное на рис. 24. Помимо типа связи, на диаграмме могут отображаться и установки ссылочной целостности - для этого необходимо выбрать в контекстном меню диаграммы пункт «Display
-34-
Рис. 24. Изображение связей в нотации IDEFIX
Options/Relationships/Referential Integrity». Обозначение ссылочной целостности на схеме представляет собой две алфавитные группы, разделенные двоеточием. Первый символ обозначает действие, к которому относится правило целостности: D - delete, I - insert, U - update. Вторая группа обеспечивает правило: R SET NULL, SD - SET DEFAULT .
Рис. 25. Диалог выбора сервера
REST RICT , с
-
CASCADE, SN
-
- 35-
Таким образом, запрет удаления обозначается — D:R, а установка NULL при изменении U :SN. Обозначения прос тавляются у родительского или дочернего конца связи, в зависимости от того, к какой сущности они относятся. Итак, мы определили на диаграмме предметную область, состоящую из четырех сущностей, описывающих материальное обеспечение процесса обучения. 2.2. СОЗДАНИЕ ФИЗИЧЕСКОЙ МОДЕЛИ БД Конечный этап моделирования БД - переход к физическому уровню модели, на котором модель также представлена в виде диаграммы. Переключите диаграмму на физический уровень. Физический уровень представления модели зависит от выбранного сервера, поэтому в первую очередь нужно определить сервер, для которого создается физическая модель. 2.2.1. ВЫБОР СЕРВЕРА Выбор сервера можно выполнить несколькими способами: • на логическом и физическом уровнях выбор можно осуществить в диалоговом окне «Diagram Editor», которое вызывается через главное меню «Edit \Diagram...»; • с помощью диалогового окна «Target Server», вызываемого через главное меню «Server\Target Server...», выбор можно осуществить только на физическом уровне. Диалог «Target Server» (рис. 25) позволяет задать тип и версию сервера, тип данных и условие NULL для вновь созданных колонок. В поле «Table Name Macro» вводится шаблон для образования имен таблиц, а в поле «index Name Macro» - шаблон для имени индексов. Некоторые опции данного диалогового окна зависят от выбранного типа сервера. Например, для сервера InterBase необходимо ввести разделитель триггеров в поле «Trigger Delimiter». Кнопка «Reset Names...» вызывает диалог «Глобальный сброс имен СУБД », позволяющий заменить все имена объектов физического лица модели таблиц, колонок, связей и т. д. на имена по умолчанию (рис. 26). Как правило, имена по умолчанию генерируются на основе имен соответствующих объектов логического уровня, причем, пробелы в них заменяются на символ «-». Кнопка «RI Defaults» вызывает диалог «Referential Integrity Defaults Editor» (Редактор умолчаний ссылочной целостнос ти), позволяющий задать набор правил ссылочной целостнос ти, присваиваемый по умолчанию каждой новой связи. После выбора сервера, ввода установок и нажатия кнопки OK ERwm предложит автоматически преобразовать типы данных, связанные с атрибутами диаграммы, в типы данных, доступные на новом сервере.
-36-
Рис. 26. Диалог глобального сброса имен СУБД
2.2.2. ТАБЛИЦЫ И КОЛОНКИ В диалоге «Target Server» предусмотрено поле для шаблона имени таблицы, в котором по умолчанию стоит вызов макроопределения %EntityName ( ). Это макроопределение устанавливает в качестве имени таблицы имя сущности логической диаграммы, что не Табл. 9. Сущности и их таблицы может устраивать, так как сервер СУЩНОСТЬ ТАБЛИЦА InterBase не допускает символов СТУДЕНТ STUDENT кириллицы в именах объектов меГРУППА GROUP таданных. Поэтому нам необхоTEACHER димо изменить имена таблиц, сге- | ПРЕПОДАВАТЕЛЬ КАФЕДРА | CATHEDRA нерированные ERwin автоматичеSUBJECT ски, на новые, не содержащие ПРЕДМ ЕТ ИЗУЧЕНИЕ ! STUDYING символов кириллицы, которые ADVANCING приведены в табл. 9. Для переиме- УСПЕВАЕМ ОСТЬ нования таблицы необходимо вызвать пункт «Table» ее контекстного меню и или выбрать в главном меню пункт «Edit\Table». При этом появится «Table Editor» (рис. 27), в списке «Table» которого выбирается необходимая таблица, а новое имя вводится в поле «Name». Здесь
— 37 —
же в поле «Owner» можно указать владельца таблицы, если он отличается от пользователя, генерирующего схему БД.
Рис. 27. Редактор таблиц
В нижней части окна содержатся следующие элементы управления: • флажок «Physical Only», который указывает, что таблица существует только на физическом уровне;
• флажок «Generate» - если он установлен, то при генерации схемы БД будет выполняться запрос CREATE TABLE; • кнопка «DB Sync» запускает процесс полного сравнения модели с физической базой, находящейся на сервере.
Кроме того, редактор таблиц содержит следующие страницы с закладками: • Comment - страница предназначена для ввода комментариев к таблице; • Volumetrics - содержит поля для ввода оценочных данных, используемых при расчете объема, занимаемого таблицей; • UDP - обеспечивает ввод значений пользовательских свойств, связанных с таблицей;
• Validation - служит для задания правил и корректности ввода данных в таблицу; • stored Procedure- служит для управления хранимыми процедурами; • Рге & Post Script - управляет сценариями, выполненными до и после генерации таблицы;
-38• Power-Builder - задаются расширенные атрибуты системы PowerBuilder для таблиц, входящих в модель. После приведения имен таблиц в соответс твие с требованиями, займемся именами и типами данных полей. Ранее, когда мы вводили домены, в редакторе словаря доменов «Domain Dictionary Editor» справа находилась закладка «InterBase», позволяющая устанавливать физические параметры домена (см. рис. 12). Важными для нас в данный момент являются параметры «InterBase Datatype» и «Null Options». Сервер InterBase поддерживает типы данных, приведенные в табл. 10.
Домены удобны, когда несколько таблиц в БД содержат одинаковые опреТабл. 10. Типы данных, поддерживаемые сервером InterBase ТИП
РАЗМЕР
ДИАПАЗОН/ТОЧНОСТЬ
BLOB
переменный
Размер сегмента ограничен 64 К
CHAR(n)
n символов
1 - 32767 байт
DATE
64 бита
DECIMAL (precision, scale)
переменный
С 1 января 100 г. по 29 февраля 32768 г. precision =1-15 общее число знаков, scale - 1 - 15 Число с scale знаков число знаков после десяпосле десятичной точтичной точки должно быть ки < или = precision
DOUBLE PRECISION
64 бита
1 .7*10-308- 1.7*1 0308
FLOAT
32 бита
3.4*10-38-3.4*1038
INTEGER
32 бита
-2147483648-2147483647
Длинное целое со знаком
NUMERIC
переменный
precision =1-15 общее число знаков, scale - 1 - 15 число знаков после десятичной точки должно быть < или = precision
Число с scale знаков после десятичной точки
SMALLINT
16 бит
-32768 - 32767
VARCHAR(n) n символов
1 - 32767 байт
ОПИСАНИЕ
Текстовая строка фиксированной длины Включает также информацию о времени
Точность до 15 знаков .
Короткое целое со знаком Текстовая строка переменной длины
деления колонок. В нашей модели это все домены полей, входящих в первичный ключ, поэтому мы создадим для них физические домены. Создадим также
-39домены для некоторых полей, которые встречаются несколько раз (t_note). Для этих доменов установите флажок «Domain», а для остальных — отключите. 2.2.3. РЕДАКТИРОВАНИЕ СВОЙСТВ ПОЛЕЙ Для редактирования свойств вызовите редактор колонок (Column Editor/ Для этого выберите пункт главного меню «Edit/Column...» (кроме того, его можно вызвать и через контекстное меню таблицы, выбрав «column Editor...»).
Рис. 28. Редактор колонок
Редактор колонок (см. рис. 28) внешне напоминает редактор атрибутов, рассмотренный ранее. Редактируемая таблица выбирается в списке «Table», находящемся в верхней части диалога. Рядом имеется кнопка, позволяющая вызвать диалоговое окно редактора таблиц «Table Editor». В левой нижней час ти редактора имеется несколько кнопок: • New - добавление новой колонки к таблице; • Rename - редактирование имени колонки; • Delete - удаление колонки; • DB Sync - запуск процесса синхронизации модели с физическим системным каталогом СУБД; • Migrate - вызывает диалог, в котором можно выбрать, какие свойства колонки должны мигрировать в колонки внешнего ключа; • Reset - позволяет установить для свойств выбранных колонок значения, заданные по умолчанию.
-40-
В правой части окна редактора находится ряд страниц с закладками: • General- обеспечивает выбор или изменение домена, к которому относится колонка. Домены представлены в виде дерева, содержимое которого может сортироваться либо по алфавиту, либо по иерархическому принципу. По флажку Physical Only можно указать, что поле относится только к физической модели, а по флажку Primary Key - включить выбранное поле в первичный ключ; • InterBase - на этой странице можно задать физические свойства колонки: тип данных, опцию NULL, правило валидации и значение по умолчанию. • Comment - используется для ввода комментария для поля; • UDP - обеспечивает создание свойств для физических полей таблицы; • index - обеспечивает создание индексов для таблицы. В окне списка показаны существующие индексы для данной таблицы. В нижней части имеется флаг «show FK index», при включении которого показываются как первичный, так и внешние индексы. Те индексы, в которых участвует выбранная колонка, помечены крестиком (см. рис. 29). Кнопка в верхнем углу вызывает диалог редактора индексов «index Editor».
Рис.29. Страница индексов
2.2.4. ГЕНЕРИРОВАНИЕ SQL-СЦЕНАРИЯ СОЗД АНИЯ БД Основной целью процесса проектирования является генерация физ ической схемы БД. Для генерации схемы БД следует выбрать пункт меню «Tasks/ Forward Engineer/Schema Generation...».
-41-
Рис. 30. Диалог генератора физической схемы БД
Физическая схема БД генерируется на основе логической схемы и набора установок, задаваемых в диалоговом окне генератора схем (рис. 30). Эти установки определяют, какие элементы должны войти в схему БД. Для каждой логической схемы можно создать несколько таких наборов установок. Текущий набор установок выбирается в списке «Option Set». Для создания нового набора установок нажмите «New» и введите имя набора «База данных InterBase» (рис. 31). В окне диалога содержатся и другие кнопки: • Rename - позволяет переименовать текущий набор установок; • Delete- позволяет удалить текущий набор установок. Для выбора установок перейдите на страницу с закладкой Options. Элементы генерируемой схемы организованы по разделам, список которых находится в левом окне страницы. В правом окне находится список элементов отмеченного раздела с флажками. Для выбора элемента, который
Рис. 31. Создание набора установок
должен использоваться при генерации схемы БД, следует проставить флажок рядом с этим элементом.
-42На странице Summary показываются элементы, выбранные на странице Options. Страница Comment обеспечивает ввод комментариев к каждой из схем генерации. В нижней части окна редактора имеется ряд кнопок: • Filter- вызывает редактор фильтра таблицы, с помощью которого выби-
Рис. 32. Диалоговое окно фильтра таблиц
раются таблицы (сущности), входящие в схему (рис. 32). Диалоговое окно фильтра состоит из двух списков, содержащих имена таблиц (переключатель «Display Names» в положении Physical) или сущностей (переключатель «Display Names» в положении Logical). В левом списке находятся имена таблиц, исключенные из схемы генерации, в правом - вошедшие в схему; • Preview - обеспечивает просмотр сгенерированного SQL-сценария создания БД. Вызванное окно содержит с тандартное текстовое окно и набор кнопок для редактирования, просмотра и печати текста сценария (рис. 31). Полученный сценарий можно сохранить в файле; кнопка «Generate» вызывает диалог генерации системного каталога БД; • Print - обеспечивает печать SQLсценария на принтере; • Report - обеспечивает сохранение Рис. 33. Диалог связи с БД SQL-сценария в текстовом файле; • Generate - запускает процесс генерации физической схемы БД. В диалоге с БД (рис. 33) необходимо ввести login и password, если это требуется. В выпадающем списке «Database» следует выбрать имя БД или оdвс-драйвера. После нажатия кнопки «Connect» появится диалог Generate Database
- 43
Schema. Для продолжения процесса генерации следует нажать кнопку «Continue». А теперь можно сгенерировать схему нашей БД. Для этого выберите пункт главного меню «Tasks/Forward Engineer/Schema Generation...». В диалоговом окне генератора схем на странице «Options» выделите в левом списке объект «Trigger» и уберите все флажки в правом списке. Нажмите «Preview». В окне просмотра появится следующий SQL-скрипт создания БД: CONNECT 'e:\ib\courses.gdb' USER '' PASSWORD '' CREATE DOMAIN t___god_rozhd DATE; CREATE DOMAIN t_ball INTEGER; CREATE DOMAIN t__chasov INTEGER; CREATE DOMAIN t_chislo_semestrov INTEGER; CREATE DOMAIN t_group_id INTEGER; CREATE DOMAIN t_kafedra_id INTEGER; CREATE DOMAIN t_kolich_student INTEGER; CREATE DOMAIN t_ocenka INTEGER; CREATE DOMAIN t_predmet_id INTEGER; CREATE DOMAIN t_student_id INTEGER; CREATE DOMAIN t_tab_nomer INTEGER; CREATE DOMAIN t_address VARCHAR(20); CREATE DOMAIN t_kafedra_name VARCHAR(20); CREATE DOMAIN t__last__f_m__name VARCHAR(20) CREATE DOMAIN t_predmet__name VARCHAR(20); CREATE DOMAIN t_progr_cours VARCHAR(20); CREATE DOMAIN t__telephone VARCHAR(20); CREATE DOMAIN t_uch_stepen VARCHAR(20); CREATE DOMAIN t_uch_zvanie VARCHAR(20); CREATE DOMAIN t_vid_zaniatiya VARCHAR(20) CREATE TABLE ADVANCING student_id group_id predmet_id tab_nomer vid_zaniatiya ocenka
t_student_id NOT NULL, t_group_id NOT NULL, t_predmet_id NOT NULL, t_tab_nomer NOT NULL, t_vid_zaniatiya NOT NULL, t_ocenka
В приведенном скрипте можно выделить несколько групп SQL-запросов: Создание доменов. Это группа SQL-запросов CREATE DOMAIN. Они генерируются для всей модели, если в опциях для объекта «Schema» установлен флажок «CREATE DOMAIN». Создание таблиц. Для каждой таблицы, входящей в текущее подмножество модели, генерируются запросы, заданные в опциях объекта Table. В данном случае это: CREAT E TABLE - создание таблицы; CREAT E INDEX - создание индекса для первичного ключа; ALT ER T ABLE... ADD PRIMARY KEY - добавление первичного ключа; ALT ER T ABLE... ADD FOREIGN KEY - добавление внешнего ключа. 2.2.5. КОД ПОДКЛЮЧЕНИЯ К БД Этот сценарий будет выполнен в программе windows ISQL (File\Run an ISQL script...), поэтому сценарий должен начинаться с команд подключения к БД: CONNECT <файл базы> USER <имя пользователя> PASSWORD <пароль>
Добавим эти команды в начале сценария. Внесем в схему текстовые параметры — имя файла БД, имя пользователя и пароль, чтобы их можно было использовать при генерации схемы. Для этого воспользуемся реализованным в ERwm механизмом пользовательских свойств.
Выберите «Edit\Diagram. . .» и перейдите на страницу «UDP» (рис. 34). Затем нажмите OK и перейдите в редактор пользовательских свойств (рис. 35). В списке «class» выбирается объект диаграммы, для которого задаются пользовательские свойства. В данном случае объектом является сама диаграмма, поэтому в поле стоит «Diagram».
Рис. 35. Редактор пользовательских свойств
Добавление пользовательского свойства производится с помощью кнопки «+» таблицы свойств. Кроме этого таблица свойств содержит колонки: • Name — имя пользовательского свойства; • Туре - тип данных свойства. Определены следующие типы данных: > Command - выполняемая строка, например, C:\MSOFFICE\ WINWORD.EXE D:\TUTORIAL\README.DOC; > Data -дата; > int - целое число; > Real - действительное число; > Text - символьная строка; > List - список. • Default- значение свойства по умолчанию; • Description - описание свойства. Введите в таблицу три свойства текстового типа: IB_DBName, IB_User_ Name, IB_Password и нажмите ок. После этого введите значения этих свойств. На рис. 36 файл БД сервера InterBase (свойство IB_DBName) имеет полное имя «Е: \IB\COURSE.GDB», В качестве login (СВОЙСТВО IB_User_Name) «STUDENT», а пароля (свойство IB__Password) - «silver». Теперь необходимо в начале генерируемого скрипта программно дописать команды подключения к базе. Для этого воспользуемся тем, что ERwin позволяет назначить каждому объекту диаграммы специальные шаблоны, написанные на встроенном макроязыке. Выберите «Server\InterBase Schema Property...». Диалоговое окно «Schema Property Editor» содержит две страницы (см. рис. 37): • stored Procedure - на этой странице схема связывается с шаблонами
-49хранимых процедур, которые генерируются при генерации схемы; • Pre & Post Script - на этой странице задаются скрипты, генерируемые при генерации схемы в целом.
Рис. 36. Пользовательские свойства ER-диаграмм
Для генерации команд подключения воспользуемся сценарием «до генерации», поэтому перейдите на страницу «Pre & Post Script» и нажмите
Рис. 37. Подключение шаблона сценария к схеме «Schema Script Template...».
-50-
Для добавления шаблона, нажмите кнопку New и введите в диалоге имя «Подключение к БД ». Введенное имя появится в колонке Script Template Name (рис. 38), в колонке Туре указывается «Рге» (этот тип можно поменять с помощью переключателя «Generation Option»,), а в колонке «Code» выводится первая с трока кода шаблона. Полный текст шаблона вводится в дополнительном окне «Schema Script Template», которое представляет собой обычный текстовый редактор (см. рис. 38).
Рис. 38. Добавление шаблона сценария к схеме
Наберите следующий текст шаблона: CONNECT ' %DiagramProp (IB_DBName)' USER '%DiagramProp (IB_UserName)' PASSWORD '%DiagramProp (IB_Password)';
При вводе текста шаблона можно вызвать на экран вспомогательное окно «Template Toolbox» (рис. 39). В левой части диалогового окна находятся списки, содержащие имена макросов, относящихся к: • сущностям (Entity Macro); • связям (Relationship Macro); • атрибутам (Attribute Macro); • ограничениям (Constrain Macro); • макросы общего назначения (Miscellaneous Macro). В центральной части в окне «Description» выводится синтаксис выделенного макроса и пример его использования для фрагмента схемы, приведенного в правой части диалога. Если дважды щелкнуть по выбранному имени макроса, то оно будет вставлено в редактируемый текст.
-51Нажмите ОК в редакторе «Schema Script Template Editor» и вернитесь в редактор свойств схемы, в верхней части которого имеется два списка - подключенных скриптов (Attached Script) и неподключенных скриптов (Unattached Script) . Написанный нами шаблон появился в правом списке, но он еще не подключен к схеме и его необходимо подключить. Для этого выделите его в схеме и нажмите на кнопку «Attach». При этом имя шаблона переместится в левый список, в окне Script Template появится текст шаблона, введенный ранее (см. рис. рис. 37), а в окне Script Expansion выводится результат работы шаблона: CONNECT ' d:\ib\course.gdb' USER 'STUDENT' PASSWORD 'silver';
Рис. 39. Вспомогательное окно Template Toolbox
В этом скрипте мы воспользовались макросом %DiagramProp (), который позволяет извлечь значение пользовательского свойства, заданного в диаграмме, по его имени. В макроязыке ERwin имеются макросы для извлечения значений свойств, приписанных к любым объектам модели. Нажмите ОК и сгенерируйте схему БД (Tasks\Forward Engineer\Schema Generation. .). В окне предварительного просмотра и убедитесь, что в начале сценария добавились строки подключения к БД.
2.2.6. ГЕНЕРАТОРЫ И ТРИГГЕРЫ В нашей модели имеются поля, введенные в качестве первичного ключа. Эти поля должны содержать генерируемые автоматически уникальные для таблицы целые числовые значения. Для реализации этой задачи необходимы два
- 52-
компонента: генератор уникального значения и триггер, который присваивал это значение при вставке новой записи. Для создания генератора в языке SQL предусмотрен запрос CREAT E GENERAT OR, а для присвоения уникального значения первичному ключу - запрос CREAT E T RIGGER. Примем правило, что генераторы будем называть по имени поля с прибавлением строки «_gen». Например, запрос на создание генератора для поля kod_group будет иметь вид CREATE GENERATOR kod_group_gen;
Такое же правило примем относительно имен триггеров, которые образуются от имени таблиц с добавлением «__ GEN_ID». Тогда имя триггера для таблицы GROUPS будет GROUP S_GEN_ID, а запрос на создание триггера: SET TERM !!; CREATE TRIGGER GROUPS_GEN_ID FOR GROUPS BEFORE INSERT AS BEGIN new.kod_group =gen_id(kod_group_gen,1); END !! SET TERM; !!
Такие запросы должны быть в сценарии создания БД после SQL-запросов создания таблиц CREAT E T ABLE для каждой таблицы, имеющей автоинкрементный ключ. А теперь для всех атрибутов создадим специальное пользовательское свойство (UDP ) , которое будет служить признаком генерирования значений. Для этого перейдите в режим логической схемы и выберите пункт меню «Edit\UDPs. . .»..
В диалоге свойств установите в списке «Class» объект «Attribute», создайте свойство с именем «generate_id» типа «List» и назначьте ему значения по умолчанию «yes_no» (рис. 40).
Рис. 40. Свойство generate_id - признак автоинкрементного поля
Это пользовательское свойство будет видно у всех атрибутов модели, а значение его по умолчанию будет равно «nо». Для генерируемых ключевых атрибутов поменяйте это значение на «yes» (см. рис. 41). Перечень ключевых автоинкрементных атрибутов приведен в табл. 11. Итак мы пометили автоинкрементные атрибуты, теперь необходимо создать
53шаблон и подключить его к указанным таблицам. Для этого перейдите в режим физической модели, выберите «Edit\Table. . .» и щелкните по закладке «Pre&Post Script».
Рис. 41. Установка значения свойства generate_id
Необходимо в этом редакторе создать скрипт и подключить к таблице. На этот раз скрипт должен иметь тип «после генерации», так как он будет содержать запрос на создание триггера, а таблица, к которой этот триггер относится, должна уже существовать. Табл. 11 . Ключевые автоинкрементные атрибуты
СУЩНОСТЬ Группы Студенты Кафедры Преподаватели Предметы Изучение Успеваемость
ТАБЛИЦА
КЛЮЧЕВОЙ АТРИБУТ
GROUPS STUDENTS KATHEDRS TEACHERS
kod_group kod_student kod_kathedra kod_teacher
SUBJECTS STUDYING RATING
!
kod_subject vid_zaniatia
Щелкните по кнопке «Script Template» и перейдите в редактор шаблонов, уже рассмотренный выше. Создайте новый скрипт с названием «Создание генератора». Для ЭТОГО В окне «Table Script Template» наберите следующий текст:
-54%ForEachAtt(%TableName) {
if (%==(%AttProp(generate_id),yes)) { CREATE GENERATOR %AttFieldName_gen; SET TERM %DBM STriggerDelim; CREATE TRIGGER %TableName_GEN_ID FOR %TableName BEFORE INSERT AS BEGIN new.%AttrFieldName=gen_id (%AttrFieldName__gen, 1) ; END %DBM STriggerDelim SET TERM ; %DBM STriggerDelim } }
Проверьте, чтобы «Generation Option» был ус тановлен в положении «PostTableCreation» и нажмите OK (рис. 42). Созданный скрипт должен появиться в правом списке - списке неподключенных скриптов. Для переноса в список подключенных скриптов выберите его и нажмите кнопку «Attach», затем выберите в выпадающем списке следующую таблицу и т. д.
Рис. 42. Создание скрипта
А теперь рассмотрим текст шаблона. Встроенный в ERwin макроязык содержит около 200 макросов, имена которых начинаются с символа «%». В тексте использован макрос %AttProp (generate_id) , который извлекает значение свойства «generate_id», подключенного к атрибуту. В макроязыке ERwin имеются макросы-операторы цикла, условные операторы и операторы сравнения. Например, для организации цикла - перебора всех атрибутов таблицы служит макрос
- 55%ForEachAtt (%TableName) {...}
Согласно данной конструкции, все, что находится в {...}, будет выполняться для каждого атрибута таблицы %TableName. Макрос %TableName при раскрытии шаблона разворачивается в имя текущей таблицы. Условный макрос %if (% == (%AttProp(generate_id), yes)) { ...
}
является аналогом условного оператора if. Здесь проверяется равенство свойства generate_id у атрибута значения «yes», и если оно равно, то выполняется все, что находится в фигурных скобках. В шаблоне используется также макроопределение имени поля %AttFieldName_gen, разворачивающееся в имя поля, соответствующее атрибуту. Например, атрибуту «kod_group» соответствует поле «kod_group_gen». В тексте шаблона используется также макрос %DBMSTriggerDelim, который заменяется при обработке шаблона в разделитель триггера - «! !». Это значение было определено в диалоге «Target Server» в поле «Trigger Delimiter».
Теперь можно проверить результаты проведенной работы. Для этого выйдите из редактора таблиц «Interbase Table Editor» и выполните генерацию схемы базы данных. В режиме просмотра можно убедиться, что после SQL - запросов создания таблиц CREAT E T ABLE появились строки создания генераторов и триггеров. Например, часть сценария, относящаяся к таблице GROUPS, выглядит теперь следующим образом: CREATE TABLE GROUPS (
kod_group kol_students name_group sredniy_ball
t_nomer NOT NULL, t_kolichestvo, t_nomer, t_sredniy_ball
); CREATE UNIQUE INDEX XPKGROUPS ON GROUPS (
kod_group ); ALTER TABLE GROUPS ADD PRIMARY KEY (kod_group); CREATE GENERATOR kod_group_gen; SET TERM !!; CREATE TRIGGER GROUPS_GEN_ID FOR GROUPS BEFORE INSERT AS BEGIN
new.kod_group = gen_id(kod_group_gen, 1); END ! ! SET TERM ; !!
- 562.2.7. ХРАНИМЫЕ ПРОЦЕДУРЫ Рассмотренный механизм шаблонов очень удобен, когда при генерации схемы требуется повторить одну и ту же операцию для нескольких объектов модели. Далее мы будем создавать хранимые процедуры вставки, изменения и удаления записей, которые будут иметь одинаковую структуру для всех таблиц. Поэтому для хранимых процедур можно создать шаблоны для вставки, изменения и удаления записей, а затем использовать их для всех таблиц базы. Запрос на создание процедуры вставки записи имеет вид SET TERM !! ; CREATE PROCEDURE <имя процедуры> (<параметр тип>, ...) AS BEGIN INSERT INTO <имя таблицы> (<имя поля>, <имя поля> ...) VALVES (<: параметр>, <: параметр> ...) END ! ! SET TERM ; !!
Здесь SQL-выражение SET T ERM устанавливает в качестве разделителя последовательность символов « ! !», а при окончании процедуры возвращает старое значение разделителя «;». Примем правило, согласно которому имя процедуры образуется от имени таблицы, путем добавления перед ним префикса «ins_». Параметрами процедуры будут все поля таблицы, кроме автоинкрементного поля, значение которого генерируется триггером. Для таблицы GROUPS процедура вставки создается следующим запросом SET TERM !! ; CREATE PROCEDURE ins_groups (name_group CHAR(30), kol_students SM ALLINT, sredniyj_ball SM ALLINT) AS BEGIN INSERT INTO PART_TYPE (equip_name,kol_students,sredniy_ball) VALUES ( : equip__name, : kol_students, : sredniy_ball) ; END ! ! SET TERM ; !!
Процедура изменения записи таблицы имеет вид SET TERM !! ; CREATE PROCEDURE <имя процедуры> (<параметр тип>, ...) AS BEGIN UPDATE <имя таблицы> SET <имя поля> = <:параметр>, <имя поля> = <:параметр> ... WHERE <ключ> = <параметр> AND <ключ> = <параметр> ... ; END ! ! SET TERM ; !!
Как и в предыдущем случае, имя этой процедуры создадим из имени таблицы, добавив к нему префикс «upd__». В отличие от предыдущей процедуры, параметры здесь должны содержать и ключевое поле, по которому устанавливается
- 57-
условие в запросе UPDAT E. Применительно к таблице дит так:
GROUPS процедура
выгля-
SET TERM !! ; CREATE PROCEDURE upd_groups (kod_group SMALLINT, name_group CHAR(30), kol_students SM ALLINT, sredniy_ball SM ALLINT)) AS BEGIN UPDATE GROUPS SET name_group =: name_group, kol_students =: kol_students, sredniy_ball =: sredniy_ball WHERE kod_group =: kod_group; END ! ! SET TERM ; !!
Процедура удаления содержит в качестве параметров только ключевые реквизиты и имеет вид SET TERM !! ; CREATE PROCEDURE del_groups (kod_group SMALLINT) AS BEGIN DELETE FROM GROUPS WHERE kod__group =: kod__group; END ! ! SET TERM ; !!
Для создания шаблонов и привязки их к таблицам вызовите редактор «Table Editor» набрав пункт главного меню «Edit/Table . . .». В вызванном редакторе перейдите на страницу «Stored Procedure»: • нажмите на кнопку «SP Template» и перейдите в редактор шаблонов «Template Editor»;
• создайте в редакторе три шаблона, назвав их «Вставка записи», «Изменение записи» И «Удаление записи»; • введите тексты шаблонов, приведенные ниже. Вставка записи SET TERM %DBM STriggerDelim; CREATE PROCEDURE ins_%Lower(%TableName) (%ForEachAtt(%TableName,',') { %if (%Not(%AttIsPK)) {%AttFieldName %AttDataType } } ) AS BEGIN INSERT INTO (%ForEachAtt(%TableName,',') {%if (%Not(%AttIsPK)) {%AttFieldName} } ) VALUES (%ForEachAtt(%TableName,',') {%if (%Not(%AttIsPK)) {:%AttFieldName} } ); END%DBM STriggerDelim SET TERM ; %DBM STriggerDelim
- 58Изменениезаписи SET TERM %DBMSTriggerDelim ; CREATE PROCEDURE upd__%Lower (%TableName) (%ForEachAtt(%TableName,',') {%AttFieldName %AttDataType}) AS BEGIN UPDATE %TableName SET %ForEachAtt(%TableName,',') {%if (%Not (%AttIsPK) ) {%AttFieldName=:%AttFieldName} } WHERE %ForEachAtt(%TableName,' AND ') {%if (%AttIsPK) {%AttFieldName=:%AttFieldName} }; END%DBM STriggerDelim SET TERM ; %DBM STriggerDelim
Удаление записи SET TERM %DBM STriggerDelim; CREATE PROCEDURE del_%Lower(%TableName) (%ForEachAtt(%TableName,',') {%if (%AttIsPK) {%AttFieldName %AttDataType } } ) AS BEGIN DELETE FROM %TableName WHERE %ForEachAtt(%TableName, ' AND ') {%if (%AttIsPK) {%AttFieldName=:%AttFieldName }}; END%DBM STriggerDelim SET TERM ; %DBM STriggerDelim
• вернитесь в редактор таблиц и подключите созданные шаблоны к таблицам: GROUPS, STUDENTS, KATHEDRAS, TEACHERS, SUBJECTS, STUDYING.
2.2.8. ИНДЕКСЫ Для повышения скорости извлечения данных и обеспечения условия уникальности значений в базах данных используется механизм индексации. При выполнении запроса СУБД в первую очередь проверяет, существуют ли подходящие индексы у таблиц, участвующих в запросе. Затем СУБД определяет, что будет эффективнее - использовать индексы или выполнять последовательный просмотр записей. Если принимается решение об использовании индекса, в индексе находится необходимое значение и по ссылкам, связанным с этим значением, находятся нужные строки таблицы. Извлечение данных с помощью индекса быстрее, т. к. индекс упорядочен и имеет небольшой размер. Но, индексы увеличивают объем базы данных, а также время вставки, удаления и изменения данных, содержащих индексные колонки, т. к. при этом необходимо изменять индексы. Но выигрыш в скорости от применения индексов намного превышает эти недостатки. Создание индексов целесообразно в следующих случаях: • колонка часто используется в условиях поиска; • колонка участвует в условиях соединения JOIN;
-59• по колонке производится сортировка. ERwin содержит средства для создания индексов в проектируемой модели. На логическом уровне индексы представлены ключевыми группами (KeyGroup) или ключами, при переходе к физической модели ключевые группы преобразуются в индексы. Ключевые группы могут быть следующих типов: • первичный ключ (Primary Key) — однозначно идентифицирует экземпляр сущности; • альтернативный ключ (Alternate Key) - это потенциальный ключ, не выбранный в качестве первичного. ERwin позволяет выделять атрибуты потенциальных ключей и при генерации схемы базы данных генерировать по этим группам отдельные уникальные индексы. • внешний ключ (ForeignKey) - создается в дочерней сущности при внесении в диаграмму связи и включает в себя мигрирующие атрибуты родительской сущности; • инверсионные входы (inversion Entry) - атрибуты или группы атрибутов, не определяющие экземпляр сущности уникальным образом, но час то использующиеся для обращения к экземплярам сущности. Классическим примером инверсного входа является атрибут «Фамилия» в таблицах, а в нашей базе данных ключом этого типа является атрибут «kod_student» таблицы ST UDENT S.
Рис. 43. Редактор ключевых групп
- 60B ERwin можно редактировать ключевые группы. Для этого предусмотрен редактор ключевых групп (рис. 43), вызываемый путем выбора пункта «Edit / Key Group...» главного меню. Перейдите в режим логической модели и выберите пункт «Edit/Key Group. . .». Редактор содержит следующие элементы управления: • Entity (сущность) - поле с выпадающим списком, в котором выбираетс я сущность для редактирования; • Key Group — окно с перечнем ключевых групп. Группы представлены строками, включающими в себя имя (Key Group) , тип (Туре) и определение ( Definition) ;
• флажок Show FK Groups, обеспечивает включение режима вывода внешних ключей в перечне.
• Кроме этого редактор ключевых групп содержит следующие страницы с закладками: • Members - для задания ключевых групп и порядка их следования в группе; • General — содержит переключатели, позволяющие задавать тип ключевой группы (для первичного и внешнего ключа эти опции не доступны); • Definition - предназначена для набора произвольной текстовой информации, относящейся к выбранной ключевой группе; • Note — предназначена для набора примечания к выбранной группе; • UDP - предназначена для установки пользовательских свойств для выбранной группы.
Рис. 44. Диалог ввода новой ключевой группы
Рассмотрим процесс редактирования ключевой группы на примере атрибута «название предмета». Выберите В списке сущность «Единица оборудования» и нажмите «New» (рис. 44). Введите имя ключевой группы в поле «Key Group» — «Название предмета». При этом в поле «Index» выводится генерируемое ERwin имя индекса, которое следует оставить без изменений. С помощью переключателя «Key Group Type» задается тип создаваемого ключа. Это может быть Alternate Key или Inversion Entry. Выберите
-61Inversion Entry и нажмите ок. После этого введенный альтернативный ключ появится в перечне ключей. Затем перейдите на страницу «Members», выберите в левом списке атрибут «Название предмета» и переместите его в правый список. Теперь, для того, чтобы при генерации схемы базы генерировались все необходимые нам индексы, следует в диалоге генерации для объекта «index» установить все флажки (рис. 45).
Рис. 45. Флажки группы «Create Index» диалога генерации схемы
Сгенерируйте SQL - скрипт создания базы данных и сохраните его в файл. CONNECT 'e:\ib\courses.gdb' USER 'ST UDENT '
address t_address, corpus no t_corpus_no, audit_no t_audit_no, telephone t_telephone, note t_note ); CREATE UNIQUE INDEX XPKCLASS ON CLASS ( class_id ); ALTER TABLE CLASS ADD PRIMARY KEY (class_id); CREATE GENERATOR class_id_gen; SET TERM !! ; CREATE TRIGGER CLASS_GEN_ID FOR CLASS BEFORE INSERT AS BEGIN new.class_id = gen_id(class_id_gen, 1); END ! ! SET TERM ; !! CREATE TABLE PART ( equip_id workplace_id equip_type_id inventory_no techinfo malfunct install__date note
t_equip__id NOT NULL, t_workplace_id, t_equip_type_id NOT NULL, t_inventory_no, t_techinfo, t_malfunct, t_install_date, t_note
); CREATE UNIQUE INDEX XPKPART ON PART (
equip_id
); CREATE INDEX XIF2PART ON PART (
workplace_id
-63); CREATE INDEX XIF6PART ON PART ( equip_type_id ); ALTER TABLE PART ADD PRIMARY KEY (equip_id); CREATE GENERATOR equip_id_gen; SET TERM !! ; CREATE TRIGGER PART_GEN_ID FOR PART BEFORE INSERT AS BEGIN
new.equip_id = gen_id (equip_id_gen, 1); END !! SET TERM ; !! CREATE GENERATOR equip_type_id_gen; SET TERM !! ; CREATE TRIGGER PART_GEN_ID FOR PART BEFORE INSERT AS BEGIN new . equip_type_id = gen__id (equip_type_id_gen, 1); END ! ! SET TERM ; !! CREATE TABLE GROUPS ( equip_type_id t_equip_type_id NOT NULL, equip_name t_equip_name
); CREATE UNIQUE INDEX XPKGROUPS ON GROUPS ( equip_type_id ); ALTER TABLE GROUPS ADD PRIMARY KEY (equip_type_id); CREATE GENERATOR equip_type_id_gen; SET TERM !! ; CREATE TRIGGER GROUPS_GEN_ID FOR GROUPS BEFORE INSERT AS BEGIN new.equip_type_id = gen_id (equip__type_id_gen, 1); END ! ! SET TERM ; !! CREATE TABLE WORKPLACE ( workplace_id t_workplace_id NOT NULL, class_id t_class_id NOT NULL, workplace_no t_workplace_no, workplace_name t_workplace__name, ip__address t_ip_address, note t note
64 CREATE UNIQUE INDEX XPKWORKPLACE ON WORKPLACE ( workplace_id ); CREATE INDEX XIF1WORKPLACE ON WORKPLACE ( class_id ); ALTER TABLE WORKPLACE ADD PRIMARY KEY (workplace_id); CREATE GENERATOR workplace_id_gen; SET TERM !! ; CREATE TRIGGER WORKPLACE_GEN_ID FOR WORKPLACE BEFORE INSERT AS BEGIN
new.workplace_id = gen_id(workplace_id_gen, 1); END ! ! SET TERM ; !! ALTER TABLE PART ADD FOREIGN KEY (equip_type_id) REFERENCES GROUPS; ALTER TABLE PART ADD FOREIGN KEY (workplace_id) REFERENCES WORKPLACE; ALTER TABLE WORKPLACE ADD FOREIGN KEY (class_id) REFERENCES CLASS; SET TERM !! ; CREATE PROCEDURE ins_class (class__id INTEGER address VARCHAR(20) corpus_no VARCHAR(20) audit_no VARCHAR(20) telephone VARCHAR(20) note VARCHAR(20) } ) AS BEGIN INSERT INTO CLASS (address corpus_no audit_no telephonenote VALUES ( : address, : corpus__no, : audit_no, : telephone, : note) ; END ! ! SET TERM ; !! SET TERM !! ; CREATE PROCEDURE upd_class (class_id INTEGER, address VARCHAR(20), corpus_no VARCHAR(20), audit no VARCHAR(20),
65telephone VARCHAR(20), note VARCHAR(20)) AS BEGIN UPDATE CLASS SET address=:address, corpus_no=:corpus_no, audit_no=:audit_no, telephone=:telephone, note=:note WHERE class_id=:class_id and address=:address and corpus_no=:corpus_no and audit_no=:audit_no and telephone=:telephone and note=:note}; END ! ! SET TERM ; !! SET TERM !! ; CREATE PROCEDURE del_class (ForEachAtt(CLASS,',') {}) AS BEGIN DELETE FROM CLASS WHERE class_id=:class_id; END ! ! SET TERM ; !! SET TERM !! ; CREATE PROCEDURE ins_part (equip_id INTEGER, equip_type_id INTEGER, workplace_id INTEGER, inventory_no VARCHAR(20), techinfo VARCHAR(20), malfunct INTEGER, install_date DATE, note VARCHAR(20) } ) AS BEGIN INSERT INTO PART (equip_type_id, workplace_id, inventory_no, techinfo, malfunct, install_date, note) VALUES (:equip_type_id, :workplace_id, :inventory_no, :techinfo, :malfunct, :install_date, :note); END ! ! SET TERM ; !! SET TERM !! ;
CREATE PROCEDURE upd_part (equip_id INTEGER, equip_type_id INTEGER, workplace_id INTEGER, inventory-no VARCHAR(20), techinfo VARCHAR(20), malfunct INTEGER, install_date DATE, note VARCHAR(20)) AS BEGIN UPDATE PART SET equip__type_id=: equip_type_id, workplace_id=:workplace_id, inventory_no=:inventory_no, techinfo=:techinfo, malfunct=:malfunct, install_date=:install_date, note=:note WHERE equip_id=:equip_id and equip__type_id=: equip_type_id and workplace_id=:workplace_id and inventory_no=:inventory_no and techinfo=:techinfo and malfunct=:malfunct and install_date=:install_date and note=:note}; END ! ! SET TERM ; !! SET TERM !! ; CREATE PROCEDURE del_part (ForEachAtt(PART,',') {}) AS BEGIN DELETE FROM PART WHERE equip_id=:equip_id; END ! ! SET TERM ; !! SET TERM !! ; CREATE PROCEDURE ins_groups (equip_type_id INTEGER, equip_name VARCHAR(20) } ) AS BEGIN INSERT INTO GROUPS (equip_name) VALUES (:equip_name); END ! ! SET TERM ; !! SET TERM !! ; CREATE PROCEDURE upd_groups (equip_type_id INTEGER, equip_name VARCHAR(20; AS
- 67 BEGIN UPDATE GROUPS SET equip_name=:equip_name WHERE equip_type_id=:equip_type_id and equip__name=: equip__name } ; END ! ! SET TERM ; !! SET TERM !! ; CREATE PROCEDURE del_groups (ForEachAtt(GROUPS,',') {}) AS BEGIN DELETE FROM GROUPS WHERE equip type_id=:equip_type_id; END ! ! SET TERM ; !! SET TERM !! ; CREATE PROCEDURE ins_workplace (workplace_id INTEGER, class_id INTEGER, workplace_no VARCHAR(20), workplace_name VARCHAR(20), ip_address VARCHAR(20), . note VARCHAR(20) } ) AS BEGIN INSERT INTO WORKPLACE (class_id, workplace_no, workplace_name, ip_address, note) VALUES (:class_id, :workplace_no, :workplace_name, :ip_address, mote); END ! ! SET TERM ; !! SET TERM !! ; CREATE PROCEDURE upd_workplace (workplace_id INTEGER, class_id INTEGER, workplace_no VARCHAR(20), workplace_name VARCHAR(20), ip_address VARCHAR(20), note VARCHAR(20)) AS BEGIN UPDATE WORKPLACE SET class_id=:class_id, workplace_no=:workplace_no, workplace_name=:workplace_name, ip_address-:ip_address, note=:note WHERE workplace_id=:workplace_id and class_id=:class_id and workplace_no=:workplace_no and workplace_name=:workplace_name and ip_address=:ip_address and
- 68note=:note}; END ! ! SET TERM ; !! SET TERM !! ; CREATE PROCEDURE del_workplace (ForEachAtt(WORKPLACE, ', ') { } ) AS BEGIN DELETE FROM WORKPLACE WHERE workplace_id=:workplace_id; END ! ! SET TERM ; !!
Для создания БД выполните следующие операции: • запустите программу windows ISQL; • выберите пункт меню «File /Create Database ...»; • в диалоге создания базы укажите: • в поле «Database» - «Е:\COURSE\DATA\course.gdb»; • В поле «User Name»- «STUDENT»;
• в поле «Password» - «silver» или другой пароль;
в мемо-поле Database Options введите следующую фразу: DEFAULT CHARACTER SET WIN1251; • нажмите кнопку «ок»; • выберите пункт меню «File/Run an ISQL Script» и укажите файл с текстом сценария.
Если все сделано правильно, после отработки скрипта программа выведет сообщение «Script Completed Successfully» (Скрипт завершен успешно). 2.3. РАЗРАБОТКА ОТЧЕТОВ Для генерации отчетов в ERwin предусмотрена программа - Report Browser (RB) . RB создает отчеты путем извлечения выборок по объектам модели и их свойствам. Эти выборки выводятся в виде таблиц, причем содержащиеся в ней данные могут различным образом сортироваться и фильтроваться.
- 69-
ГЛАВА 3. СОЗДАНИЕ КЛИЕНТСКОГО ПРИЛОЖЕНИЯ ДЛЯ РАБОТЫ С БД
После создания БД и ознакомления с основами технологии доступа к данным в Delphi, необходимо разработать программу («клиентское приложение»), которая позволит манипулировать с данными, хранящимися в базе. Клиентское приложение отправляет серверу запрос, выполненный на языке SQL, а сервер производит с данными необходимые манипуляции. При этом клиентское приложение должно выполнять следующие операции: • Подключение к серверу БД, ввод имени пользователя и пароля; • Формирование запроса к серверу и получение результатов; • Представление данных в удобном для пользователя виде. • Добавление и удаление данных, навигация по набору данных.
Выше был рассмотрен первый этап процесса создания БД, в результате которого определены структуры таблиц, созданы пустые таблицы и установлены необходимые связи между ними. Технология создания целостной БД, в которой между таблицами установлены уже упомянутые связи, предполагает упорядочение загрузки взаимосвязанных таблиц при обеспечении пользователя удобным интерфейсом. Такая технология строится на использовании соответствующих экранных форм ввода\вывода. Разработчики Delphi заложили модульный принцип разработки клиентских приложений, в соответствии с которым программа делится по «формам» - программным окнам, где каждой форме соответствует свой собственный программный модуль - unit. Но при компиляции и сборке программы все эти модули объединяются в один исполняемый файл. Формы в процессе работы вызываются с разной частотой, но при организации в виде одного исполняемого файла они все равно загружаются в память и занимают в ней место. В среде Windows можно поместить исполняемый код в библиотеки DLL, которые можно загружать и выгружать во время выполнения, что позволяет строить весьма компактные приложения. При использовании данной технологии каждый диалог можно было бы вынести в отдельный модуль, который будет загружаться только тогда, когда в нем будет необходимость. Для организации этих модулей в единую программу необходимо некоторое связующее звено, которое будет загружаться первой, и выполнять загрузку нужных DLL, представляя собой оболочку для всех остальных форм. Последовательность наших действий по созданию пользовательского приложения будет следующей: • для доступа к данным созданной нами базы данных из программы Delphi, создадим псевдоним этой базы; • создадим оболочку приложения - координационный центр, из которого будут вызываться все остальные формы приложения;
-70-
• создадим объекты, соответствующие объектам БД, а также диалоговые окна приложения для манипуляции ими; • установим связи и взаимные вызовы диалогового окна приложения; • создадим отчеты по заданным темам. 3.1. СОЗДАНИЕ БАЗЫ ДАННЫХ Выше мы рассмотрели вопросы анализа ПрдО и проектирования БД с помощью CASE-средства ERwin. Здесь мы рассмотрим полный цикл создания БД. При этом кроме ERwin воспользуемся утилитой IBConsole (см. рис. 46), входящей в состав пакета InterBase и позволяющей выполнять все необходимые операции ПрдО конфигурированию сервера, созданию и администрированию БД на сервере, а также запускать запросы SQL в интерактивном режиме. Окно программы IBConsole состоит из следующих элементов: •- меню, содержащее команды администриРис. 46. Окно программы IBConsole рования сервера; • панель инструментов, с кнопками быстрого доступа к командам меню; • окно с деревом, отображающим иерархию серверов и баз данных, зарегистрированных в IBConsole; • рабочее окно, содержащее специфическую информацию, а также позволяющее выполнять различные дейс твия в зависимости от выбранной ветви иерархического дерева; • с трока состояния, в которой содержится информация о выбранном сервере и пользователе, а также подсказки меню. 3.1.1. СОЗДАНИЕ «КОНТЕЙНЕРА» БАЗЫ ДАННЫХ Серверная БД - это «набор» объектов (данные, триггеры и т.д.), которые хранят в файле. Этот «пустой» файл мы и будем интерпретировать как контейнер» БД. 1. Создайте папку для хранения базы данных. Пусть это будет Е: \COURSE\ DATA.
2. Запустите утилиту IBConsole (Пуск/InterBase/IBConsole). 3. Выделите мышью Local Server, как показано на рис. 47.
- 71 4. Используя Server\Login, зарегистрируйтесь как администратор под именем SYSDBA и паролем masterkey 5. Выберите команду Database\Create Database (рис. рис. 49).
6. Для новой БД необходимо указать ее псевдоним. Введите в поле Alias псевдоним, с которым вы хотели бы ассоциировать создаваемую БД. Этот псевдоним служит для идентификации БД внутри сервера InterBase и не связан с псевдонимом BDE.
7. В поле File (s) введите имя файла базы данных, включая полный путь. 8. Для работы с символами национальной кодировки установите значение Default Charaсter Set ПОЛЯ Options равным WIN1251. 9. Завершите работу, щелкнув мышью на кнопке ОК.
Рис. 49. Описание БД
-72Как только БД будет создана, IBConsole добавит псевдоним к дереву «сервер/базы данных», как показано на рис. 48. Теперь можно создавать таблицы БД. Поскольку это BDE-ориентированное приложение, то предварительно необходимо создать алиас для БД COURSE . GDB. 3.1.2. СОЗДАНИЕ ПСЕВДОНИМА ДЛЯ СЕРВЕРНОЙ БД Для того чтобы можно было обращаться к данным созданной нами базы данных из программы Delphi, необходимо, прежде всего, создать псевдоним этой базы с помощью программы BDE Administrator.
1. Выберите в главном меню следующий пункт «Пуск\Программы\Вог1апс1 Delphi 5\BDE Administrator». 2. Выберите команду «Object\New». 3. В выпадающем списке выберите тип драйвера БД - InterBase и ок. В окне альясов появиться новый алиас INT ERBASEI. Наберите вместо наименования по умолчанию другое наименование «T EACHER» (рис. 50).
Рис. 50. Окно программы BDE Administrator
4. В правой части окна BDE Administrator находится таблица с параметрами настройки. Для привязки создаваемого приложения к вашей БД введите в этой
- 73-
таблице следующие изменения. LANGDRIVER - Pdox ANSI Cyrilic; SERVERNAME -
d: \ib\courses. qdb (диск на ваше усмотрение).
USERNAME - STUDENT.
5. Для
сохранения
нового
псевдонима
выберите
в
меню
пункт
«Object\Apply».
6. Закройте программу BDE Administrator. 3.1.3. СОЗДАНИЕ SQL-СЦЕНАРИЯ И ОБЪЕКТОВ БАЗЫ ДАННЫХ 1. Проведите анализ вашей предметной области, выявите в ней все сущности и установите между ними необходимые связи. 2. С полученной концептуальной схемой выполните все действия, описанные в главе 2. 3. После выполнения всех предписанных действий (построения сущностей, доменов, таблиц, установление связей между таблицами, генераторов, триггеров И хранимых процедур) Выберите В ERwin пункт Меню Task\Forward Engineer\Schema Generation....
4. В открывшемся окне InterBase Schema Generation нажмите кнопку Preview и ознакомьтесь с SQL-сценарием создания вашей БД в окне InterBase Schema Generation Preview. 5. После ознакомления с текстом SQL-сценария закройте окно InterBase Schema Generation Preview. В окне InterBase Schema Generation нажмите кнопку Report. В открывшемся диалоге Generate InterBase\SQL Schema Report выберите диск, необходимую папку, присвойте имя файлу SQLсценария и нажмите ОК. Файл с SQL-сценарием будет сохранен. 6. В полученном сценарии проведите некоторые исправления: 6.1. Проследите за тем, чтобы запросы CREAT E PROCEDURE, CREATE T RIGGER были обрамлены командами SET TERM. Дело в том, что точка с запятой '; ' для утилиты InteractiveSQL означает конец оператора, а каждый оператор, заключенный в разделители, должен быть выполнен. Чтобы этого не произошло в момент создания триггера или хранимой процедуры, команда SET T ERM !! ; назначает разделителем операторов ' ! ! ' взамен '; ' . Новый разделитель не инициирует выполнения операторов в запросах создания триггеров и хранимых процедур. После завершения оператора CREAT E PROCEDURE или CREAT E T RIGGER производится обратная установка SET T ERM ; ! ! . Ваша задача - проследить, чтобы эти команды были на месте, а если они отсутствуют - вставьте их вручную. 6.2. Замените двойные кавычки одинарными. 6.3. Если вы установили связь с БД с помощью IBConsole, а в SQLсценарии содержится сгенерированный код установки связи CONNECT
'Е:\COURSE\DAT A\COURSE.GDB'
- 74USER 'SYSDBA' PASSWORD 'masterkey'
вручную удалите этот фрагмент кода. 6.4. Сохраните скорректированный SQL-сценарий. 7. Откройте IBConsole, выделите в дереве Local Server, выберите пункт меню Server\Login и в открывшемся диалоге войдите под своим именем и паролем. 8. Выделите в дереве алиас вашей базы с красным крестиком и выберите пункт меню Database\Connect. Связь с контейнером вашей БД установлена. 9. Для создания БД нажмите кнопку InteractiveSQL на панели инструментов. Появляется окно утилиты InteractiveSQL. 10. Выберите пункт меню Query\Load Script и в появившемся диалоге выберите файл с SQL-сценарием. Текст выбранного сценария появляется в верхнем окне утилиты InteractiveSQL. 11. Нажмите кнопку Execute Query на панели инструментов утилиты InteractiveSQL. Если в вашем SQL-сценарии нет ошибок, то ваша БД будет создана. Если же появляется сообщение об ошибке, то вернитесь в текст и исправьте ошибки. Итак, БД для вашего варианта создана, теперь прис тупаем к созданию пользовательского приложения.
3.2. ОБОЛ ОЧКА КЛИЕНТСКОГО ПРИЛОЖЕНИЯ 3.2.1. СОЗДАНИЕ ПРОЕКТ НОЙ ГРУППЫ В Delphi существует возможность объединения нескольких проектов в одну группу. Создание проектов полезно, например, в том случае, если приложение использует динамически загружаемые библиотеки, разрабатываемые совместно с ним. И приложение, и библиотеки DLL являются отдельными проектами, поэтому при их совместной разработке логично объединить их в одну группу проектов. Для создания группы проектов выполните следующее: 1. Запустите программу Delphi. Выберите «File\New» и выделите иконку проектной группы (Project Group) и ок. На экране появиться окно Project Manager, содержащее название проектной группы по умолчанию - ProjectGroupi. Сохраните проектную группу в новом каталоге COURSE под именем UchebnyProcess. Этот каталог будет главным каталогом нашего проекта. 2. Исполняемый файл проекта будет храниться в главном каталоге COURSE, a под библиотеки DLL создадим отдельные подкаталоги внутри него. Основной проект будем именовать main, а используемые им DLL диалогами dlglib0l, dlglib02, ...
-75-
3.2.2. СОЗДАНИЕ МОДУЛЯ uMain 1. Добавьте в группу новый проект, выбрав в командном меню группы пункт «Add new project», а затем в диалоговом окне иконку «Application». Сохраните проект в главном каталоге COURSE под именем main, модуль unit1 - под именем uMain (рис. 51).
Рис. 51. Сохранение проекта в главном каталоге
2. Окно main будет основным диалоговым окном нашей программы и должно содержать главное меню разработанной системы. Поместите на форму компонент TMainMenu, а для редактирования главного меню выберите в инспекторе свойство Items и щелкните по нему два раза. Табл. 12. Пункты меню (план и реализация на форме) РАЗДЕЛ М ЕНЮ
I ПУНКТ М ЕНЮ
Система Учебный процесс ?
! Связь с сервером... Завершить сеанс Выход Группы Студенты группы Кафедры Преподаватели кафедры Предмет и его программа Изучение предмета Успеваемость по предмету Помощь О программе
3. Для создания пункта или раздела меню необходимо выделить «пустой» пункт в редакторе меню и ввести наименование пункта в инспекторе в свойство Caption. Создайте меню с разделами и пунктами, приведенными в табл. 12.
- 76Разделы меню приложения «Учебный процесс» у нас пока пусты, мы будем добавлять в него пункты по мере разработки приложения. Для улучшения восприятия пункты меню могут отделяться разделительной чертой, которая вставляется в меню, если вместо наименования пункта внести символ «-».
Рис. 52. Основная форма приложения
4. Кроме меню поместите на форму компонент statusBar и задайте его свойство SimplePanel = true. «Оболочка» основной формы нашего приложения будет иметь вид, приведенный на рис. 52.
Это приложение должно быть центром, координирующим работу всех остальных элементов. Кроме координации работы программы, это приложение осуществляет связь с БД, поэтому оно содержит еще и компоненты, осуществляющие эту связь. 3.2.3. СОЗДАНИЕ МОДУЛЯ UDM Как нам уже известно, приложения Delphi связываются с серверами БД через «борландовскую машину баз данных» (BDE). Все функции доступа выполняются в контексте сессии связи с BDE (одной или нескольких). Так как Delphi является объектно-ориентированной средой разработки, механизм доступа реализован в виде двух компонентов - TSession и TDatabase. Любое приложение, работающее с БД через BDE, всегда содержит хотя бы один компонент TSession, который обладает массивом ссылок на связанный с данной сессией БД, количество которых можно определить ПрдО свойству DatabaseCount. TSession создается автоматически при инициализации модуля ' DBT ables ' сразу после запуска программы. Если в секции 'uses' имеется модуль ' DBTables', в приложении обязательно создается объект TSession, для доступа к которому в среде Delphi определена переменная Session. Свойство SessionName этого объекта устанавливается равным 'Default'. Пока Session не содержит в списке Databases никаких БД, поэтому его свойство DatabasesCount=0.
-77-
Компонент TDatabases появляется при активизации соединения. Допустим, что после запуска программы при нажатии одной из кнопок формы вызывается метод Query.Open. После этого производится проверка, имеется ли БД с именем, указанным в свойстве DatabaseName компонента Queryl, если ее нет, то создается новый объект т Database и ссылка на него добавляется в список Databases, в противном случае берется существующий объект TDatabase. У компонента TDatabase имеется свойство LoginPromt типа boolean, показывающее, надо ли выводить стандартный входной диалог: Если это значение равно true, то после вызова метода Open на экране появлется стандартный входной диалог. Если значение LoginPromt=false, то пользователь должен сам передать в объект TDatabase login и пароль, поместив их в список Params. По умолчанию объект TDatabase создается только в процессе соединения, поэтому нам необходимо заранее создать свой собственный компонент TDatabase И связать его С TQuery. Итак, работающая с БД Delphi-программа предс тавляет собой довольно длинную цепочку взаимоувязанных компонент, в основании которой находится список SessionList. Этот список, как мы уже отметили, всегда содержит хотя бы одну сессию. На другом конце цепочки находится какой-нибудь визуальный компонент.
Можно поместить все невизуальные компоненты для работы с БД непосредственно на форму. В этом случае взаимосвязь компонентов приложения и таблиц БД и используемые при этом свойства компонентов будут иметь вид, как это показано на рис. 53.
Рис. 53. Взаимосвязь компонентов и БД при размещении всех компонентов на форме
Но для невизуальных компонентов в Delphi предусмотрен особый тип формы, называемый модулем данных (Data Module). Этот модуль предназначен для размещения только невизуальных компонентов, таких как DataSourse и TQuery. Таким образом, компоненты, предназначенные для доступа к данным, размещаются в отдельном контейнере - модуле данных. Существует три типа модуля данных:
-78-
Рис. 54. Взаимосвязь компонентов и БД при использовании модуля данных
• простой модуль данных; • удаленный модуль данных; • Web-Модуль.
В приложениях, работающих в рамках локальной сети, используются простые модули данных, поэтому мы будем иметь дело с простым модулем данных, представленным объектом DataModule. При использовании простого модуля данных взаимосвязь компонентов приложения и БД имеет вид, показанный на рис. 54. Для создания простого модуля данных: 1. Добавьте в программу модуль данных, выбрав пункт меню File/New и щелкнув по кнопке Data Module на странице New. Поместите на страничку Components компоненты TDataSourse, TDataBase, TQuery, TStoredProc (рис. 55). В левой панели при этом появляется дерево, отображающее все связи между компонентами, а также позволяющее изменять эти связи. 2. Установите для компонента Databasel свойство DatabaseName равным TEACHER. Это приведет к появлению имени БД в соответствующей ветке дерева на левой панели.
Рис. 55. Модуль данных с компонентами доступа к данных данным
Рис. 56. Дерево компонентов модуля данных
Рис. 57. Иерархия компонентов модуля после редактирования
- 793. Дерево поддерживает режим «перетаскивания», то есть вы можете перемещать мышкой его элементы, формируя новые связи между ними. Например, вы можете перенес ти мышкой элемент DataSoursel на ветку «Queryl» (рис. 56). Этим вы подключите компонент Queryl к источнику данных DataSoursel. При этом у компонента DataSoursel устанавливается свойство DataSet = Queryl. Таким же образом можно перенести ветку Queryl на элемент DataBasel (рис. 57). В результате мы получаем дерево, содержащее объект Session с именем Default, который, в свою очередь, содержит БД T EACHER. Доступ к этой БД осуществляется через компоненты Queryl и DataSoursel. При обращении к содержащимся в модуле данных компонентам для них указывается составное имя, в которое, кроме имени компонента, входит также имя модуля данных. Мы привели стандартную схему создания модуля данных. Но как мы описали выше, наша программа содержит оболочку, которая по требованию пользователя вызывает DLL-библиотеки, с размещенными на них формами. Оболочка приложения, содержащая модуль данных, создает только соединение с БД, поэтому в модуле данных мы оставим только компонент Database1. А собственно источник данных и прочие компоненты типа Query и TStoredProc вынесем в DLL. В результате модуль данных будет выглядеть так: unit uDM ; interfасе uses
{ Public declarations } function GetSessionHandle: HDBIDB; end; var fDM : TfDM ; implementation {$R *.dfm) function TfDM.GetSessionHandle: HDBIDB; begin result:=Session.Databases[Session.DatabaseCount-1].Handle; end; end.
Обратите внимание, что для получения описателя (дескриптора) БД в модуле UDM создана специальная функция - метод GetSessionHandle. Выражение Session.Databases[Session.DatabaseCount-1]
является указателем на последнюю БД в массиве (в нашем случае она является и единственной).
- 803.3. СВЯЗЬ С БАЗОЙ ДАННЫХ Доступ к информации, хранимой в БД общего пользования, необходимо ограничивать или санкционировать. Для большинства SQL-серверов защита реализуется на уровне имени пользователя и пароля. Подключением пользователя к БД управляет компонент типа TDatabase. У него имеется свойство LoginPromt, определяющее необходимость вывода входного диалога. Если LoginPromt =f alse, то пользователь сам организует ввод и передачу имени пользователя и пароля в массив параметров Params. Поэтому в первую очередь необходимо создать форму входного диалога. Пользователь с помощью этой формы набирает имя пользователя и пароль, которые по окончании работы с диалогом должны быть доступны оболочке приложения. Для передачи этих данных из DLL в модуль главного приложения используется следующий прием: • в основном приложении создается некоторая структура, содержащая переменные для передачи данных; • указатель на эту структуру передается в DLL в качестве параметра процедуры или функции;
• вызываемая процедура из DLL в процессе работы изменяет переменные, входящие в структуру, обращаясь к ней через переданный указатель. После создания модуля DLL для формы входного диалога в проекте создается модуль для хранения структуры, создаваемой в виде класса. И, наконец, последний шаг в главном модуле: организуется вызов DLL и передача данных, сформированных в ходе работы DLL, в главный модуль. 3.3.1. СОЗДАНИЕ ПРОЕКТА DLL_LOGIN 1. Создайте в группе проектов COURSE новый проект. Для этого в Менеджере проектов в контекстном меню выберите пункт «Add New Project», а в появившемся диалоге на странице New - значок DLL. 2. Сохраните проект Projectl под именем login в каталоге dll_login, который следует создать в основном каталоге приложения COURSE. 3. Создайте подкаталоги COURSE\DCU и COURSE\EXE. Выберите пункт меню Project\0ptions и в появившемся окне Project Options for Login.dll на странице Directories\Conditionals установите параметры Unit Output Directory = COURSE\DCU, Output Directory = COURSE\EXE.
4. Модуль входного диалога является частью проекта, однако, присутствует в нем только в виде описания типа. Для того чтобы им воспользоваться, нам необходимо самим создать экземпляр этого диалога путем вызова конструктора: fLogin := TfLogin.Create(Application);
-81а после использования — уничтожить при помощи деструктора: fLogin.Free;
Лучше всего это сделать, поместив все эти вызовы в одну функцию, и сделав ее доступной внешним приложениям, т. е. экспортировать. Назовем эту функцию. Добавьте в файл проекта раздел exports: library login; uses SysUtils, Classes, uLogin in 'uLogin.pas' {fLogin}; {$R *.RES} exports ShowLoginDialog name 'SHOWLOGINDIALOG'; begin end.
Саму функцию ShowLoginDialog определим в модуле uLogin, только что подключенном нами к проекту. 5. Проект login.dll должен компилироваться раньше, чем основной проект, поэтому в группе проектов переместите его на самый верх. 3.3.2. СОЗДАНИЕ ПРОГРАММНОГО КЛАССА При описании общей схемы диалога в разделе 3.3.5 был описан процесс передачи данных из DLL в основное приложение с помощью специальной структуры, содержащей переменные для хранения передаваемых данных. Реализуем эту структуру в виде класса в отдельном модуле. 1. Добавьте в проект login.dll новый модуль, выбрав пункт меню FIе\New\Unit. Delphi добавит к проекту новый модуль, создав его с именем по умолчанию Unitl. Сохраните его под именем uLoginData в новом каталоге COURSE\common.
2. Добавьте в модуль раздел type и наберите следующее определение класса: type TLoginData = class modalResult : TModalResult; user id, password : shortstring; constructor create; end;
С помощью конструктора свойствам класса присваиваются начальные значения. Чтобы закончить создание конструктора, поставьте курсор на любую строку определения класса и нажмите SHIFT +CTRL+C. Delphi автоматически создаст заготовки всех методов, входящих в класс; в данном случае - это заго товка конструктора Create.
-82constructor TLoginData.Create begin inherited; M odalResult: = 0; user_id: = ''; password: = ''; end;
Кроме того, добавьте в раздел uses модуль Controls, чтобы использовать стандартный тип TModalResult, заданный в этом модуле. В окончательном варианте uLoginData должен выглядеть следующим образом: unit uLoginData; interface uses Controls type TLoginData = class modalResult : TM odalResult; user_id, password : shortstring; constructor create; end; implementation {TLoginData} constructor TLoginData.Create begin inherited; M odalResult: = 0; user_id: = ' '; password: = ' '; end; end;
Рис. 58. Форма входного диалога
-833.3.3. СОЗДАНИЕ ФОРМЫ ДИАЛОГА Теперь после проведения предварительной подготовки можно приступить к разработке формы входного диалога, которая будет реализована в отдельном модуле. 1. Добавьте в проект новую форму (File\New\Form) . Отредактируйте ее и переименуйте компоненты, как показано на рис. 58. Сохраните модуль в каталоге проекта под именем uLogin. 2. Установите значения свойств компонентов в соответствии с таблицей: КОМПОНЕНТ
СВОЙСТВО
fLogin biMinimize biMaximize BorderStyle Caption Position
{ Public declarations } LoginData: TLoginData; end; procedure ShowLoginDialog(Handle: THandle; p: pointer); var fLogin: TfLogin; implementation {$R *.DFM} procedure ShowLoginDialog(Handle: THandle; p: pointer); begin Application.Handle := Handle; fLogin := TfLogin.Create(Application); fLogin.LoginData:=TLoginData(p); fLogin.ShowM odal; fLogin.Free; end; procedure TfLogin.FormShow(Sender: TObject); begin ebPassword.Text:=''; end; procedure TfLogin.btnOkClick(Sender: Tobject); begin LoginData.user_id:=ebUserName.Text; LoginData.password:=ebPassword.Text; LoginData.modalResult:=mrOK; end; procedure TfLogin.btnCancelClick(Sender: Tobject); begin LoginData.M odalResult:=mrCancel; end; end.
Рассмотрим процедуру ShowLoginDialog. В качестве второго параметра этой процедуры использован указатель, на класс TLoginData. Такой же указатель добавлен и в раздел public определения самого входного диалога: public {Private declaration} LoginData: TLoginData;
Полученный указатель присваивает члену класса LoginData с использованием преобразования типа fLogin.LoginData: = TLoginData(p);
-85Этот член класса введен для удобства обращения к переданному классу из других процедур диалога, а именно из обработчиков нажатия кнопок «ок» и «ОТ МЕНА».
При нажатии «ок» происходит передача введенных пользователем пароля и имени в класс TLoginData: LoginData.user_id: = ebUserName.Text; LoginData.password: = ebPassword.Text; LoginData.M odalResult: = mrOk;
При нажатии кнопки «ОТ МЕНА» передается значение modalResult, информирующее о том, что нажата кнопка отмены, LoginData.M odalResult:=mrCancel;
Для удаления прежнего введенного значения пароля при повторном вызове входного диалога в модуль введена процедура Formshow. Скомпилируйте проект login.dll и после этого в каталоге COURSE появится файл login.dll. 3.3.4. ОРГАНИЗАЦИЯ ВЫЗОВА ВХОДНОГО ДИАЛОГА В ГЛ АВНОМ МОДУЛЕ Теперь займемся вызовом входного диалога из основного приложения. Так как для передачи данных между DLL и основной программой мы воспользовались классом TLoginData, то необходимо обеспечить видимость этого класса и из основной программы. 30. С этой целью подключите к проекту main находящийся в подкаталоге Common файл uLoginData.pas. При этом дерево группы примет вид, приведенный на рис. 59.
Рис. 59. Дерево проектной группы
- 862. Отредактируйте процедуру, отвечающую за подключение к БД так, чтобы она выглядела следующим образом: unit uM ain; interface uses Windows, M essages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, M enus, ComCtrls; type TfM ain = class(TForm) M ainM enul: TM ainM enu; M ainM enul: TM ainM enu; N1 TM enuItem; N2 TM enuItem; N3 TM enuItem; N4 TM enuItem; N5 TM enuItem; N6 TM enuItem; N7 TM enuItem; N8 TM enuItem; N9 TM enuItem; N10: TM enuItem; N11: TM enuItem; N12: TM enuItem; N13: TM enuItem; N14: TM enuItem; StatusBarl: TStatusBar; procedure N2Click(Sender: TObject); procedure N3Click(Sender: TObject); procedure NSClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var fM ain: TfM ain; implementation uses uDM; ($R *.dfm} procedure TfM ain.N3Click(Sender: TObject); type TShowLoginDialog = procedure(Handle: THandle; p: pointer); var hLib: Thandle; ShowLog in Dialog: TShowLo.ginDialog; LoginData: TLoginData; begin hLib := LoadLibrary('LOGIN.DLL'); if hLib < 32 then
- 87begin ShowM essage('Отсутствует библиотека LOGIN.DLL'); Exit end; LoginData := TLoginData.Create; ShowLoginDialog := TShowLoginDialog(GetProcAddress(hLib, 'SHOWLOGINDIALOG')); ShowLoginDialog(Application.Handle, LoginData); FreeLibrary(hLib); if LoginData.M odalResult=mrOK then begin try with fDM .Databasel do begin if Connected then Close; //LoginPromt:=false; Params.Values['PASSWORD'] := Trim(LoginData.password) ; Params.Values['USER NAM E'] := Trim(LoginData.user_id); Open; end; StatusBarl.SimpleText := 'Соединение выполнено.'; except StatusBarl.SimpleText := 'Ошибка подключения к БД.'; end; end; end; procedure TfM ain.N4Click(Sender: TObject); begin with fDM .Databasel do begin if Connected then Close; end; StatusBarl.SimpleText:='Отключение выполнено.' end; procedure TfM ain.N5Click(Sender: TObject); begin N4Click(Sender); Application.Terminate; end; end.
В приведенной процедуре производятся все манипуляции с DLL: загрузка ее в память, вызов экспортируемой процедуры и вход в базу с использованием введенных имени и пароля, поэтому рассмотрим ее подробнее. Загрузка DLL в память. Для загрузки DLL в память используется функция LoadLibrary: hLib: = LoadLibrary('LOGIN.DLL' );
Эта функция возвращает описатель (хэндл) загруженной библиотеки.
- 88-
Причем если DLL уже загружена в память, то будет возвращен описатель загруженной библиотеки - повторно она загружаться не будет. В этом проявляется основное достоинство использования DLL : несмотря на то, что DLL используется несколькими программами, она загружается в память только один раз. Для проверки успешнос ти загрузки, используется следующий фрагмен т программы: if hLib<32 then begin ShowM essage ( ' Отсутствует Login.dll'); Exit; end;
Здесь проверяется, не является ли возвращаемое функцией LoadLibrary значение < 32. Определение адреса экспортируемой процедуры. После успешной загрузки DLL необходимо найти адрес экспортируемой процедуры. Для этого используется функция GetProcAddress: ShowLoginDilog:= TShowLoginDialog(GetProcAddress(hLib,'SHOWLOGINDIALOG'));
Найденный адрес процедуры присваивается специально объявленной переменной, имеющей процедурный тип, объявленный здесь же в разделе type: type TShowLoginDialog = procedure(Handle: Thandle; p: pointer); var ShowLoginDialog: TShowLoginDialog;
Создание экземпляра класса TloginData. Кроме того, создается экземпляр класса TloginData, который будет передаваться этой процедуре: LoginData: = TLoginData.Create;
Вызов процедуры ShowLoginDialog. И только после проведения описанных подготовительных процедур, производится вызов процедуры ShowLoginDialog, экспортируемой ИЗ DLL: ShowLoginDialog(Application.Handle,LoginData);
Именно здесь создается и выводится на экран диалоговое окно ввода пароля, а введенные данные передаются в класс LoginData. После выполнения своих функций DLL выгружается из памяти: FreeLibrary(hLib);
Использование данных, полученных с помощью DLL. Далее мы работаем с классом LoginData. В первую очередь проверяется, была ли нажата кнопка ок. Если нет, то вообще ничего делать не надо. Если клавиша ок была нажата, то выполняется обычное подключение к БД, предварительно отключив
- 89стандартный входной диалог и подставив пароль и login,: LoginPromt: = false; Params.Values['PASSWORD']: = Trim(LoginData.password); Params.Values['USER NAM E']: = Trim(LoginData.user_id);
Откомпилируйте проект и запустите программу. При выборе пункта меню «Связь с сервером...» на экране появится диалоговое окно для ввода пароля. На этом создание заготовки клиентского приложения закончено. Далее, по мере изложения, модуль main будет изменяться. 3.3.5. ОБЩАЯ СХЕМА РАБОТЫ ПРИЛОЖЕНИЯ ПРИ ПОДКЛЮЧЕНИИ К БД В сжатом, схематическом изложении, созданный процесс подключения к БД описывается следующим образом: • начинает работу главный модуль uMain; • после выбора пункта меню «Система\Связь с сервером .. .»: > главный модуль uMain загружает DLL в память; > инициализируется указатель на структуру TLoginData, размещенной в модуле uLoginData; > инициализируется указатель на функцию showLoginDialog, размещенной в модуле uLogin; • управление передается модулю uLogin: > uLogin создает форму для ввода данных; > пользователь вводит данные в элементы ввода формы; > пользователь нажимает кнопку ок, и данные заносятся в элементы структуры TLoginData из модуля uLoginData. Это возможно благодаря тому, что в раздел uses модуля uLogin введен модуль uLoginData, а в описании класса формы TfLogin объявлен указатель LoginData; • управление снова передается главному модулю: • DLL выгружается из памяти; > свойству LoginPromt компонента Database присваивается значение false, а данные из элементов структуры TLoginData загружаются в массив Params; > компонент Database по полученным данным производит подключение к БД и выводится сообщение ' Соединение выполнено ' ;
> выполняется работа с БД путем вызова одной из библиотек DLL, которые будут описаны ниже; > после завершения работы с БД, выгружается DLL для работы с БД, выбирается пункт меню «Система\Завершить сеанс ...» и на этом работа с приложением завершается.
Описанная схема приведена на рис. 60.
-90-
Рис. 60. Схема подключения к БД
3.4. ДИАЛОГОВЫЕ ОКНА
3.4.1. ОБЩАЯ СХЕМА СОЗДАНИЯ ДИАЛОГОВЫХ ОКОН В ходе разработки БД нами были созданы таблицы, соответствующие сущностям ПрдО (см. табл. 13). Для манипуляции данными, хранящимися в таблицах БД, в клиентском приложении следует создавать классы, соответствующие сущностям ПрдО, а для редактирования экземпляров этих классов необходимо создать диалоговое окно. При этом каждой сущности должны соответствовать два вида окон - форма элемента и форма списка. Форма элемента ~ это диалоговое окно, которое служит для ввода и редактирования атрибутов экземпляра сущности. В общем виде она должна выглядеть как
-91показано на рис. 61 (а). На форме содержатся несколько полей ре- Табл. 13. Объекты, выделенные в процессе дактирования, условно отмечен- анализа прикладного окна ных как «Параметр». Форма ра- Сущности ПрдО Таблицы БД ботает в двух режимах: GROUPP, • В режиме ввода нового эк- Список группы земпляра поля редактирования | Список студентов STUDENT KATHEDRA очищаются. Для внесения нового | Список кафедр экземпляра сущности для всех Список преподавателей TEACHER таблиц предусмотрена хранимая | Предметы PREDM ET процедура, План проведения занятий STUDYING называющаяс Экзаменационная ведомость RATING • В режиме редактирования, значения параметров текущего экземпляра сущности заполняются из БД, чтобы пользователь мог их изменить. Для изменения значений параметров экземпляров сущностей для всех таблиц предусмотрена хранимая процедура upd__<имя_таблицы>. • Внесение нового экземпляра или изменений в БД осуществляется нажатием кнопки «Да». • Нажатием кнопки «Отмена» осуществляется выход из диалога без сохранения изменений. Форма списка, общий вид которой приведен на рис. 61 (б), отображает на экране перечень экземпляров сущности. На форме предусмотрен элемент отображения списка и четыре кнопки: При нажатии кнопки «Добавить ...» вызывается форма элемента в режиме ввода. При нажатии кнопки «Свойства ...» вызывается форма элемента в режиме редактирования.
Рис. 61. Форма элемента (а) и форма списка (б)
- 92• Кнопка «Удалить» производит удаление выделенного элемента из таблицы БД. Для удаления экземпляров сущностей для всех таблиц предусмотрена хранимая процедура del__<имя_таблицы>.
3.4.2. ПОДГОТОВКА К СОЗДАНИЮ ДИАЛОГОВЫХ ОКОН В ходе дальнейшей разработки пользовательского приложения для каждой сущности БД будем создавать формы описанных типов. Поэтому определим их как базовые классы, которые будут использованы при создании форм списка и форм элемента. Для этого следует создать их и внести в репозитарий. 1. Выберите проект main.exe и добавьте в него новую форму (File\New Form) . По умолчанию Delphi создаст ее с именем Forml, а соответс твующий модуль - Unitl. Помес тите на нее две кнопки и компоненты для работы с БД TDataSource, TDataBase, TStoredProc (рис. 62). Рис. 62. Форма fBaseElemForm 2. С помощью Object Inspector установите указанные в табл. 14 значения свойств. 3. Сохраните модуль в подкаталоге COURSE/Common как uBaseElemForm. 4. Теперь внесите форму в репозитарий, для чего щелкните по свободному месту формы плавающее командное меню и выберите команду меню формы «Add to Repositary...». 5. Заполните поля диалогового окна, как показано на рис. 63. Табл. 14. Значения свойств компонентов, размещенных на форме fBaseElemForm Компонента Forml Button 1
Button2 DataSourcel DataBasel StoredProcl
Свойство BorderStyleName Name Caption Name ModalResult Caption Name ModalResult DataSet DatabaseName DatabaseName
Значение BsDialog FBaseElemForm Отмена BtnCancel MrCancel OK BtnOK MrOKl StoredProcl ' TEACHER i TEACHER
В поле «Description» можно ввести текстовую информацию о форме. В поле «Author» укажите свою фамилию и нажмите «ок». Удалите форму из проекта main. Для этого выделите ее в дереве группы, выберите в командном
-93меню «Remove From Project» и подтвердите удаление. Файл этой формы сохранен в каталоге проекта Common и будет использоваться при создании новых форм на ее основе. Точно также следует создать и базовую форму списка, от которой будут наследоваться все такие диалоговые окна. 1. Добавьте в проект main новую форму. 2. Установите на нее четыре кнопки и компоненты - список TListBox, а также TDataSource, TDataBase, TStoredProc, как это было сделано выше. Табл. 15. Значения свойств компонентов, размещенных на форме fBaseElemForm Компонента Forml
DataSourcel
Свойство BorderStyle Name Caption Name Caption Name Caption Name Caption Name DataSet
3. Кроме того, вставьте дополнительно компонент TQuery (рис. 64 и табл. 15). 4. Сохраните модуль в подкаталоге COURSE/Common как uBaseListForm.
5. По аналогии с предыдущей формой поместите форму в репозитарий и удалите его из проекта. Теперь все готово для создания диалогового окна. Как мы договорились, каждый диалог будет храниться в отдельной библиотеке DLL. Для каждого объекта будет создан программный класс, описание которого должно помещаться в отдельном модуле, хранящемся в каталоге Common. Кроме того, мы создадим форму элемента и форму списка для каждого из объектов. Имена объектов и имена форм и модулей приведены в табл. 16. В ней приняты следующие соглашения для именования форм и модулей: • DLL и каталог проекта, в котором она создается, будем именовать dlglib
94Табл. 16. Классы диалоговых окон Каталог объекта dlglib0l dlglib02 dlglib03 dlglib04 dlglib05 dlglib06
Класс
TStudents TKathedrs
ucKathedrs
Список преподавателей Предметы
dlglib07 dlglib08 dlglib09 dlglib10
TTeachers
ucTeachers
TSubject
ucSubject
План проведения занятий Экзаменационная ведомость
dlglibll dlglibl2
TStudying
ucStudying
dlglibl3 dlglib14
TRating
ucRating
Объект прикладног о окна Список группы Список студентов Список кафедр
Модуль класса ucGroups
TGroups ucStudents
Форма элемента/ форма списка feGroups flGroups fe Students fl Students feKathedrs flKathedrs feTeachers flTeachers feSubject flSubject feStudying flStudying feRating flRating
3.4.3. ДИАЛОГОВЫЕ ОКНА ДЛЯ ТАБЛИЦЫ GROUPS
3.4.3.1. СОЗДАНИЕ ПРОЕКТА DLGLIB01 1. Создайте в группе UchebyProcess новый проект. Для этого следует в командном меню группы выбрать «Add new project» и выбрать в диалоговом окне значок DLL. 2. Сохраните новый проект Projectl под именем dlglib0l в каталоге dlglib0l, который следует создать в основном каталоге приложения Course. 3. Переставьте проекты, входящие в группу UchebyProcess таким образом, чтобы главный модуль main.exe компилировался последним (рис. 65).
Рис. 63. Окно добавления формы в репозитарий
Рис. 64. Форма fBaseListForm
- 95
Рис. 65. Проекты, входящие в группу
3.4.3.2. СОЗДАНИЕ ПРОГРАММНОГО КЛАССА Теперь создадим программный класс для работы с данными таблицы Groups. Объект «Группы» представлен в моделировании данных сущностью ГРУППЫ (табл. 17), которой на физическом уровне соответствует таблица GROUPS. Создаваемый программный класс TGroups должен обладать элементами, которые соответствовали бы атрибутам сущности, а значит колонкам таблицы БД, показанными выше. Табл. 17. Атрибуты сущности «Группы» Сущность ГРУППЫ
Атрибут Код группы Название группы Количество студентов Проходной балл
Тип данных . Number
Имя колонки БД kod_groupp
String Number Real
name_groupp kol students sredny_ball
4. Выберите меню «File/New» и выберите значок модуля Unit. Сохраните добавленный модуль Unitl под именем ucGroups.pas в каталоге Common.
5. Введите определение класса TGroups, как показано на листинге: unit ucGroups; inte rface type
Класс TGroups содержит четыре элемента - kod__group, name_group, kol__students и sredniy_ball, имена которых совпадают с именами полей таблицы БД. Кроме этого, у класса имеется свойство - признак changed, который используется для того, чтобы определить, изменились ли значения остальных членов класса. Понятно, что TGroups является наследником базового класса TObject.
3.4.3.3. СОЗДАНИЕ ФОРМ Ы ЭЛЕМ ЕНТА Теперь создадим форму элемента. 1. Добавьте к проекту dlglib0l новую форму элемента, воспользовавшись помещенной в репозитарий формой «Базовая форма элемента». Для этого необходимо выбрать в меню «File/New», а затем в диалоговом окне «New Item» указать на странице «Forms» значок «Базовая форма элемента» И ОК. В нижней части диалогового окна «New item» имеется переключатель, позволяющий выбрать способ, которым форма из репозитария будет вставлена в проект. Он имеет несколько положений: • Сору - в проекте создается точная копия выбранной формы или модуля данных из репозитария. • inherit - наследование - это наиболее гибкий способ использования форм. Он особенно эффективен, когда на основе одной формы из репозитария в приложении создается несколько однотипных форм. При наследовании в проект включается базовая форма из репозитария, кроме того, создается новая форма, класс которой является наследником класса из репозитария. • Use - используемая форма добавляется в проект, и изменения в ней затронут все другие приложения, которые тоже используют эту форму. В первую очередь этот режим предназначен для модулей данных. Так как каждая DLL содержит у нас только одну форму, мы используем копирование. Нажмите ОК. Сохраните новый модуль unitl в каталоге dlglib0l под именем ueGroups. Рис. 66. Форма fBaseElemForml
- 972. Поместите на форму по три компонента TEdit, TLabel и скомпонуйте ее, как показано на рис. 66. Значения свойств компонентов должны быть заданы так, как показано в табл. 18. Табл. 18. Значения свойств компонентов fBaseElemForml и Label1
Свойство \ Значение \ Name feGroups Caption Группы Caption Обозначение группы Text ........... • _ .......... Caption Количество студентов Text Caption Проходной балл Text
3. Дополните описание класса формы, как показано на листинге TfeGroups = class(TForm) btnCancel: TButton; btnOK: TButton; DataSourcel: TDataSource; StoredProcl: TStoredProc; Databasel: TDatabase; Labell: TLabel; Editl: TEdit; Label2: TLabel; Edit2: TEdit; LabelS: TLabel; Edit3: TEdit; private {Private declarations} Groups: TGroups; public
(Public declarations} procedure CloseProc; function GetElement: Boolean; function InsElement: Boolean; function UpdElement: Boolean; end;
По этой схеме в приложении будет создано большинство форм элемента. Здесь Groups - указатель класса, который используется для передачи данных о редактируемом объекте. Как уже говорилось выше, форма может быть использована в двух режимах - в режиме ввода и в режиме редактирования. То есть, вызывая эту форму, следует указать, в каком именно режиме должна отработать, поэтому процедура вызова должна иметь примерно следующий вид: procedure ShowElemDlg(const DlgM ode: Boolean);
-98Пусть параметр DlgMode имеет значение true для режима вставки и false — для режима редактирования. Кроме того, понадобятся процедуры создания диалога и настройки связи с БД. procedure CreateElemDlg (Handle : Thandle, p : pointer ); procedure SetElemConnection (const PBHandle : HDBIDB);
Эти три процедуры будут импортироваться из DLL. Теперь рассмотрим методы класса TfeGroups. Процедура CloseProc введена для удобства, так как операция закрытия набора данных применяется достаточно часто. procedure TfeGroups.CloseProc; begin if StoredProcl.Active then StoredProcl.Close; end; Функции GetElement, InsElement И UpdElement шадки» нашей формы:
Здесь речь идет о таблице GROUPS. Организация доступа к хранимым процедурам. Проектируя БД в предыдущей части, мы предусмотрели хранимые процедуры для манипулирования данными - в случае таблицы GROUPS это были процедуры ins_groups, upd_groups и del_groups, которые производят вставку, изменение и удаление типа оборудования (табл. 19). Табл. 19. Хранимые процедуры, определяемые для обработки данных в таблице GROUPS
! Тип данных CHAR (30) SMALLINT SMALLINT CHAR (30) SMALLINT SMALLINT SMALLINT SMALLINT CHAR (30)
Недос тает процедуры, которая позволяла бы извлечь из БД информацию о типе данных по его коду. Для ее создания запустите windows ISQL и подключитесь к БД Courses,
- 99созданной в конце предыдущего раздела. Наберите в окне запроса следующий текст: CREATE PROCEDURE get_groups (kod_group SMALLINT) RETURNS (name_group char(30)) AS BEGIN SELECT name_group FROM GROUPS WHERE kod_group=:kod_group INTO :name_group; END
Эта процедура имеет два параметра - входной параметр kod_group и выходной параметр name_group. В теле процедуры имеется обычный запрос на выборку данных, и полученное значение name_group помещается в выходной параметр, к которому могут обращаться внешние приложения. Выполните запрос, и если все набрано правильно, то в БД будет создана новая процедура get__groups. Создайте в любом текстовом редакторе файл addon. sql и скопируйте в него текст созданной процедуры. Сохраните addon, sql в каталоге, в котором вы держите сценарий создания БД. Этот файл будет дополнительным файлом сценария, который необходимо запустить при создании БД. Теперь у нас есть полный комплект хранимых процедур для манипулирования данными таблицы GROUPS.
Для работы с хранимыми процедурами Delphi имеет специальный компонент TstoredProc, который является наследником TDataSet и имеет все его методы и свойства. В то же время, он имеет несколько свойств и методов, специально предназначенных для работы с хранимыми процедурами: StoredProcName - имя хранимой процедуры типа string. Во время проектирования его можно выбрать из выпадающего списка, подключившись к БД. Во время выполнения программы оно задается операцией присваивания: StoredProcl.StoredProcName:='ins groups';
Params - параметры хранимой процедуры, как входные, так и выходные. Свойство Params имеет тип TParams и является коллекцией - особого рода списков. Работа с ним похожа на работу со свойством Fields. Во время проектирования Params вызывает диалоговое окно редактора, в котором можно добавлять параметры и задавать их различные свойства. Каждый параметр обладает следующими свойствами: • Name — имя параметра, имеет тип string; • DataType - тип данных. Нам понадобятся следующие: ftstring - символьный; ftSmallInt - 16 битное число; ftlnteger - 32 битное число; ftBoolean — булевское;
- 100ftFloat —дробное; ftDataTime - дата и время.
• ParamType - тип параметра. Может принимать следующие значения: ptUnknown - неопределенный; ptInput - входной параметр; ptOutput- выходной параметр; ptInputoutput - входной и выходной параметр одновременно; ptResult - возвращаемое значение. Кроме того, имеется большой набор свойств модификаторов, позволяющих присваивать параметру значение и считывать его: As integer, AsString, AsFloat, As Boolean И Т. Д. Во время выполнения программы параметры создаются функцией CreateParam, которая добавляет новый параметр в коллекцию и сразу же устанавливает его имя, тип и тип данных: function CreateParam (FldType:TfileType; const ParamName: string; ParamType: TParamType): TParam;
Так как эта функция возвращает указатель на созданный параметр, удобно использовать ее в конструкции with ... do. Например, чтобы добавить входной параметр name_groupp, можно использовать подобный фрагмент: with StoredProcl.Params.CreateParam(ftString,
'name_groupp', ptlnput)
do begin AsString:= Groups.name_groupp; end
Для удаления всех параметров коллекция Params имеет метод Clear: StoredProcl.Params.Clear;
Выполнение хранимых процедур осуществляется в два этапа: Подготовка. При этом производиться подготовка параметров, так называемое «связывание». Кроме этого на этом этапе инициализируются BDE и SQL серверу посылается сообщение о том, что хранимая процедура готова к выполнению. Подготовка выполняется методом Prepare. Собственно выполнение. Существуют два вида процедур: процедуры, возвращающие набор данных, и процедуры, не возвращающие набор данных. Выполнение первых производиться при помощи метода Open или путем присвоения свойству Active значения true. Для выполнения вторых используется метод ЕхесРгос. Описание функций вызова хранимых процедур. Создайте метод insElement и наберите его текст:
- 101function TfeGroups.InsElement : Boolean; begin try result : =true; CloseProc; StoredProcl . StoredProcName : = ' ins_groups ' ; StoredProcl . Params . Clear; with StoredProcl. Params .CreateParam (ftString, ' name_group ' , ptlnput) do begin Groups . name_group := Editl.Text; AsString := Groups . name_group ; end; StoredProcl . Prepare; StoredProcl . ExecProc; except result : =false ; end; end;
Имя хранимой процедуры задается при помощи свойства StoredProcName : StoredProcl . StoredProcName : =' ins_part__type' ;
Затем очищаются все параметры, и в список параметров добавляются параметр name_group, значение которого берется из поля ввода Editl. После этого производится подготовка и собственно выполнение хранимой процедуры. Функция InsElement возвращает результат выполнения процедуры true, если выполнение прошло успешно и false в случае возникновения исключения.
Точно так же выглядит функция модификации данных upd_element : function TfeGroups . UpdElement : Boolean; begin try result : =true; CloseProc; StoredProcl . StoredProcName : = ' upd_groups ' ; StoredProcl. Params .Clear; with StoredProcl . Params . CreateParam (ftlnteger, ' kod_group ', ptlnput ) do begin Aslnteger := Groups . kod__group; end; with StoredProcl . Params . CreateParam (ftString, 'name_group' , ptlnput) do begin Groups . name_group := Editl.Text; AsString := Groups. name group; end; with StoredProcl . Params . CreateParam (ftlnteger,
- 102'kol_students' , ptInput) do begin Groups.kol_students:= Edit2.Text; Aslnteger := Groups.kol_students; end; with StoredProcl.Params.CreateParam (ftFloat, 'sredniy_ball',ptInput) do begin Groups.Changed:=true; Groups.sredniy_ball:= Edit3.Text; AsFloat := Groups.sredniy_ball; end; StoredProcl.Prepare; StoredProcl.ExecProc; except result:=false; end; end;
Так как хранимая процедура принимает четыре входных параметра, то в список Params добавляется четыре члена - kod_group, name_group, kol_ students и sredniy ball. В момент выполнения этой функции мы полагаем, что указатель Groups содержит ссылку на существующий экземпляр класса TGroups, откуда и берется код изменяемой группы kod_group. Значение наименования name__group передается из Editl. Это же значение заносится в объект Groups, для использования в вызывающем модуле. Значение наименования kol_students передается из Edit2 и так же заносится в объект Groups. Значение наименования sredniyball передается из Edits и заносится в объект Groups. Свойству changed присваивается значение true, как признак того, что данные изменились. И, наконец, хранимая процедура get_groups, которую мы только что создали, вызывается в программе следующим образом: function TfeGroups.GetElement: Boolean; begin try result:=true; CloseProc; StoredProcl.StoredProcName:='get groups'; StoredProcl.Params.Clear; with StoredProcl.Params.CreateParam(ftInteger,
Кроме входного параметра kod_group, здесь создаются выходные параметры StoredProcl.Params.CreateParam(ftString,'name_group',ptOutput); StoredProcl.Params.CreateParam(ftInteger, 'kol_students ' , ptOutput); StoredProcl.Params.CreateParam(ftFloat,'sredniy_ball', ptOutput);
После выполнения процедуры результат (наименование группы, количество студентов в группе и средний балл группы) помещается в объект Groups, a также в поля Editl, Edit2, Edit3 для редактирования. Groups.name_group:=Trim(StoredProcl.Params[1].AsString); Editl.Text:=Groups.name_group; Groups.kol_students:=Trim(StoredProcl.Params[2].Asnteger); Edit2.Text:=Groups.kol_students; Groups.sredniy_ball:=Trim(StoredProcl.Params[3].AsFloat); Edit3.Text:=Groups.sredniy_ball;
Операция удаления пробелов Trim здесь необходима, так как хранимая процедура возвращает результат со всеми пробелами. Процедуры, экспортируемые из DLL. Теперь займемся процедурами, которые будут экспортироваться из DLL и вызываться другими модулями. Таких процедур мы определили три: procedure CreateElemDlg (Handle:Thandle; p:pointer); procedure SetElemConnection(const DBHandle:HDBIBB); procedure ShowElemDlg (const Dl-gM ode : boolean) ;
Первые две процедуры не содержат ничего нового - здесь производилось создание диалогового окна и подключение к БД, как показано в следующих двух листингах:
- 104procedure CreateElemDlg (Handle: Thandle; p: pointer); begin Application.Handle:=Handle; feGroups:=TfeGroups.Create(Application); if assigned(p) then feGroups.Groups:=TGroups(p); end; procedure SetElemConnection(const DBHandle: HDBIDB); begin feGroups.Databasel.Handle:=DBHandle; end;
Рассмотрим подробнее процедуру showElemDlg: procedure ShowElemDlg (const DlgMode:boolean); begin with feGroups do begin if DlgMode then begin {диалог вызван для вставки элемента} Editl.Text:=''; ShowModal; if modalResult = mrOK then if not InsElement then ShowMessage ('Ошибка при внесении элемента в БД'); end else begin if GetElement then begin ShowModal; if ModalResult=mrOK then begin if not UpdElement then ShowMessage('Ошибка при изменении элемента в БД. Kod:'+IntToStr (Groups.equip_type_id)); end; end else ShowMessage ('Ошибка при извлечении элемента из БД. Kod:'+ IntToStr(Groups.equip_type_id)); end; Free ; end; end;
В зависимости от значения, переданного в параметре DlgMode, данная функция выполняет ввод или редактирование данных. Если DlgMode=true, выполняется ввод нового элемента. Перед вызовом диалогового окна на экран поле Editl очищается. Затем вызывается окно диалога и, если была нажата кнопка ок, производится попытка внести элемент в
- 105БД. В случае ошибки выдается сообщение «Ошибка при внесении элемента в БД».
Если DlgMode=false, то перед вызовом диалогового окна, оно заполняется данными при помощи функции GetElement. Далее в зависимости от нажатой кнопки производится изменение данных. Экспортируемые функции должны быть описаны в модуле проекта DLL, поэтому добавьте в файл dlglibOl.dpr раздел exports. Файл проекта должен выглядеть следующим образом: library dlglibOl; USES
SysUtils, Classes, ueGroups in ucGroups in
' ueGroups . pas ' { feGroups } ; '..\common\ucGroups.pas',
ueG ucGroups in '..\common\ucGroups.pas', {$R *.res} exports CreateElemDlg name 'CREATEELEMDLG', SetElemConnection name 'SETELEMCONNECTION', ShowElemDlg name 'SHOWELEMDLG'; begin end.
Обратите внимание, что в директиве uses имя - ссылка на модуль BDE - это необходимо для того, чтобы был виден тип HDBIDB. Откомпилируйте и постройте dlglibOl.dll.
3.4.3.4. СОЗДАНИЕ ПРОЕКТА dlglib02 В клиентском приложении созданная форма элемента будет вызываться из формы списка. При нажатии на кнопку «Добавить...» она должна вызываться в режиме вставки, а при нажатии на кнопку «Свойства...» - в режиме редактирования. Теперь создадим форму списка для объекта «Группы».
1. Создайте в группе новый проект - DLL и сохраните его в отдельном каталоге course\dlglib02 ПОД именем dlglib02 . dpr. Установите в свойствах проекта главный каталог course в качестве выходного каталога (диалог «Options», на страничке «Directories/Conditionals» параметр «Output Directory»). 3.4.3.5.
СОЗДАНИЕ ФОРМ Ы СПИСКА
1. Добавьте к проекту dlglib02 новую форму, воспользовавшись помещенной в репозитарий формой «Базовая форма списка» и нажмите «ОК». Для этого выберите пункт меню «File\New\other. . .», а затем в окне «New item» на странице «Forms» укажите значок «Базовая форма списка» и нажмите на кнопку «ок». Внешний вид формы списка практически готов, следует изменить только имя формы и заголовок окна Caption (табл. 20).
- 106Сохраните модуль под именем ulGroups . pas в каталоге dlglib02. Перейдем к редактированию класса Tf iGroups. Так же, как и класс предыТабл. 20. Значения свойств компонента fBaseElemForml
Компонент fBaseElemForm
Свойство I Name 1 Caption
Значение flGroups Группы
дущей формы, он должен содержать в секции Private указатель на класс TGroups — связующее звено с другими модулями, а также несколько методов: private {Private declaration} Groups: TGroups; procedure CloseDataSet; function LoadList: boolean; function DelElement: boolean;
Процедура close DataSet закрывает активные наборы данных, которых имеется два: storedProcl - для выполнения хранимых процедур и Queryl для получения выборки. procedure TflGroups.CloseDataSet; begin if StoredProcl.Active then StoredProcl.Close; if Queryl.Active then Queryl.Close; end
Выборку данных и внесение их в список ListBoxl осуществляет функция LoadList. Но перед описанием функции скажем несколько слов о компоненте TListBox, который предназначен для вывода на экран строковых списков, в которых могут выбираться элементы. Ядром TListBox является свойство items, которое и содержит список, отображаемый на экране, items - это потолок абстрактного класса TStrings, специально предназначенного для хранения списков строк. Его можно представить как последовательность связанных друг с другом параметров «указатель на класс TObject» - «строка» (рис. 67). Доступ к строкам производится через свойство strings с указанием порядкового номера элемента, например: ListBoxl.Items.strings[2].
Помимо строк список содержит также указатели на объекты, обращаться к которым надо через свойство objects: ListBoxl. items.Objects [2] - указатель на 3-й объект. Количество элементов в списке определяется свойством count. Для добавления элементов в список класс имеет следующие методы:
- 107-
Рис. 67. Структура абстрактного класса TStrings, предназначенного для хранения списков строк function Add(cons S:string): Integer; function AddObject(cons S:string; Aobject: TObject): Integer;
Функция Add добавляет в список строку, устанавливая ссылку на объект, равной nil, а функция AddObject добавляет и строку, и ссылку на объект. В списке TlistBox пользователь обычно выбирает какую-нибудь строку, номер которой определяется по свойству Itemindex. Все эти свойства и методы используются в функции LoadList, текст которой приведен ниже: function TflGroups.LoadList; begin try try result:=true; ListBoxl.Items.Clear; CloseDataSet; Queryl.SQL.Clear; Queryl.SQL.Add('select kod_group, name_group'); Queryl.SQL.Add('from GROUPS'); Queryl.SQL.Add('order by name_group'); Queryl.Open; while not Queryl.EOF do begin ListBoxl.Iterns.AddObject(Queryl.Fields[1].AsString, TObject(Queryl.Fields[0].Aslnteger)); Queryl.Next; end; btnProp.Enabled:=false; btnDelete.Enabled:=false;
Для получения данных на сервере выполняется запрос на выборку SELECT kod_group, name_group FROM GROUPS ORDER BY name_group;
который передается в компонент Queryl. Результирующий набор данных перебирается в цикле while ... do и заносится в список: ListBoxl.Items.AddObject(Queryl.Fields[1].AsString, TObject (Queryl.Fields[0].AsInteger));
Здесь вместо ссылки на объект в свойство objects заносятся целые числа — коды типов оборудования, над которыми выполняется преобразование типа. Извлечь такое значение можно при помощи конструкции Integer(ListBoxl.Items.Object[<№ элемента>])
Функция DelElement не отличается от функций, расмотренных в предыдущем модуле dlglib0l: function ТflGroups.DelElement:boolean; begin try result:=true; CloseDataSet; StoredProcl.StoredProcName: = 'del_groups'; StoredProcl.Params.Clear; with StoredProcl.Params.CreateParam (ftlnteger, 'kod_group', ptInput) do begin AsInteger:=integer(ListBoxl.Items.Objects [ListBoxl.Itemlndex]); end; StoredProcl.Prepare; StoredProcl.ExecProc; ListBoxl.Items.Delete(ListBoxl.Itemlndex); except result:=false; end; end;
Как и в функциях, созданных ранее, здесь используется класс storedProc, выполняющий хранимую процедуру del_groups. В качестве значения параметра kod_group ей передается код типа оборудования из выделенной строки в списке. После удаления строки с этим кодом из БД она удаляется и из списка.
- 109Теперь, как и в предыдущем случае рассмотрим процедуры, которые будут экспортироваться из DLL и вызываться другим и модулями. Таких процедур три: procedure CreateListDlg(Handle:THandle; p:pointer); procedure SetListConnection(const DBHandle:HDBIBB); procedure ShowListDlg;
Первая процедура создает диалоговое окно, вторая - производит подключение к БД, а третья - загружает и освобождает диалоговое окно. procedure CreateListDlg (Handle: Thandle; p: pointer); begin Application.Handle:=Handle; flGroups:=TfIGroups.Create(Application); if assigned(p) then flGroups.Groups:=TGroups(p); end; procedure SetListConnection(const DBHandle: HDBIDB); begin flGroups.Databasel.Handle:=DBHandle; end; procedure ShowListDlg; begin with flGroups do begin if LoadList then begin ShowModal; flGroups.Free; end; end; end;
Экспортируемые функции должны быть описаны в модуле проекта DLL, поэтому добавьте в файл dlglib02 .dpr раздел exports. Файл проекта должен выглядеть следующим образом: library dlglib02; uses SysUtils, Classes, ulGroups in 'ulGroups.pas' {flGroups}; ucGroups in '..\common\ucGroups.pas', {$R *.res} exports CreateListDlg name 'CREATELISTDLG', SetListConnection name 'SETLISTCONNECTION', ShowListDlg name 'SHOWLISTDLG';
- 110begin end.
Обратите внимание, что в директиве uses имя - ссылка на модуль BDE - это необходимо для того, чтобы был виден тип HDBIDB. Откомпилируйте и постройте dlglib02.dll. Вызов функции осуществляется в обработчике кнопки «Удалить», который следует создать: procedure TflGroups.btnDeleteClick(Sender:TObject); begin if Application.M essageBox('Удалить группу из базы?', 'Учебные курсы', M B_ICONQUESTION+M B_YESNO)=IDYES then begin if not DelElement then ShowM essage('Ошибка при удалении записи из БД. Код:' +IntToStr(Groups.kod_group)); end; end;
Для добавления и изменения данных наступило время воспользоваться уже готовой dlglibOl. dll. procedure TflGroups.btnAddClick(Sender:TObject); type TCreateElemDlg=procedure(Handle: THandle; p:pointer); TSetElemConnection=procedure(const DBHandle:HDBIDB); TShowElemDlg=procedure(const DlgMode:boolean); var hLib:THandle; CreateElemDlg: TCreateElemDlg; SetElemConnection: ТSetListConnection; ShowElemDlg: TShowListDlg; PGroups: TGroups; begin hLib:=LoadLibrary('DLGLIB01.DLL'); if h Lib < 32 then begin ShowMessage('Отсутствует библиотека'); Exit; end; CreateElemDlg:=TcreateElemDlg(GetProcAddress(hLib, 'CREATEELEMDLL')); SetElemConnection:=TsetElemConnection(GetProcAddress (hlib, 'SETELEM CONNECTION')); ShowElemDlg:=TshowElemDlg(GetProcAddress (hlib, 'SHOW ELEMDLG')); PGroups:=TGroups.Create; CreateElemDlg(Application.Handle,PGroups);
- 111SetElemConnect ion (DataBase!.Handle); ShowElemDlg(true); If PGroups.changed then LoadList; FreeLibrary(hlib); end;
Собственно вызов формы производится в несколько этапов: •- создается пустой экземпляр класса PGroups, который должен передаваться в форму элемента PGroups: =TGroups. Create; • создается ОКНО CreateElemDlg (Application. Handle, PGroups); • устанавливается связь с БД, причем, диалогу передается все тот же Handle базы SetElemConnection (DataBasel. Handle) полученный из main;
• диалог вызывается на экран в режиме вставки нового элемента ShowElemDlg(true). После вызова формы элемента в свойство changed объекта PGroups показывает, была ли выполнена операция внесения в БД, т. к. пользователь мог просто нажать «Отмена». Если данные внесены (changed = true), то список ListBox загружается заново, чтобы отобразить произведенные изменения. Точно также производится и динамический вызов DLL в обработчике кнопки «Свойства» btnPropClick. procedure TflGroups.btnPropClick(Sender:TObject); type TCreateElemDlg=procedure(Handle: THandle; p: pointer); TSetElemConnection=procedure(const DBHandle: HDBIDB); TShowElemDlg=procedure(const DlgMode: boolean); var hLib: THandle; CreateElemDlg: TCreateElemDlg; SetElemConnection: TSetElemConnection; ShowElemDlg: TShowElemDlg; PGroups: TGroups; begin hLib:=LoadLibrary('DLGLIB01.DLL'); if hLib < 32 then begin ShowMessage('Отсутствует библиотека'); Exit; end; CreateElemDlg:=TCreateElemDlg(GetProcAddress(hLib, 'CREATEELEMDLL'));
{создаем объект для передачи данных в форму элемента}
- 112PGroups:=TGroups.Create; with PGroups do begin {в объект вносятся данные из списка-наименование и код} kod_group:=integer(ListBo xl.Items.Objects [ListBoxl.Itemlndex]); name_group:=ListBoxl.Items[ListBoxl.Itemlndex]; kol__students:=integer(ListBoxl.Items.Objects [ListBoxl.Itemlndex]); sredniy ball:=real(ListBoxl.Items.Objects [ListBoxl.Itemlndex]); end; CreateElemDlg(Application.Handle,PGroups); SetElemConnection (DataBasel.Handle); ShowElemDlg(false); if PGroups.changed then LoadList; FreeLibrary(hLib); end;
От созданного ранее оно отличается тем, что при создании диалога в него передается не «пус той» объект PGroups, а содержащий данные из выбранной строки списка ListBox. Кроме того, диалог вызывается в режиме изменения - в процедуру ShowElemDlg передается параметр false. При выходе из формы нажатием на кнопку «Выход» - данные из выбранной строки списка ListBoxl сохраняются в объекте Groups, если он существует: procedure TflGroups.btnExitClick(Sender:TObject); begin if ListBoxl.Itemlndex <> -1 then begin if assigned (Groups) then with Groups do begin kod_group:=integer(ListBo xl.Items.Objects [ListBoxl.Itemlndex]); name__group : =ListBo xl. I terns [ListBoxl.Itemlndex]; kol__students:=integer(ListBoxl.Items.Objects [ListBoxl.Itemlndex]); sredniy_ball:=real(ListBoxl.Items.Objects [ListBoxl.Itemlndex]); end; end; end;
Здесь мы исходили из того, что форма списка, скорее всего, будет использоваться для выбора элемента - значит, выбранный элемент каким-то образом будет нужно передавать вызывающему модулю. Именно для этого
- 113мы и используем ссылку на объект Groups, которая передается параметром при создании диалога и присваивается, если не равна nil: if assigned(p) then flGroups.Groups:=TGroups(p); Полный текст модуля ul Groups приведен в следующем листинге: unit ulGroups; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DBTables, DB, StdCtrls, ucGroups, BDE; type TfIGroups = class(TForm) ListBoxl: TListBox; btnAdd: TButton; btnProp: TButton; btnDelete: TButton; btnOK: TButton; DataSourcel: TDataSource; Databasel: TDatabase; StoredProcl: TStoredProc; Queryl: TQuery; procedure btnDeleteClick(Sender:TObject); procedure btnAddClick(Sender:TObject); procedure btnPropClick(Sender:TObject); procedure btnExitClick(Sender:TObject); private Groups: TGroups; procedure CloseDataSet; function LoadList: boolean; function DelElement: boolean; public { Public declarations } end; procedure CreateListDlg (Handle: Thandle; p: pointer); procedure SetListConnection(const DBHandle: HDBIDB); procedure ShowListDlg; var flGroups: TfIGroups; implementation {$R *.dfm} j **************************************************************** i { Процедура закрытия активных соединений, если они имеются } г *******#********************#******•*********************•*•*•*• I
procedure TfIGroups.CloseDataSet; begin if StoredProcl.Active then StoredProcl.Close; if Queryl.Active then Queryl.Close;
- 114end; { Загрузка списка групп из базы данных } 1***********************************************************} function TfIGroups.LoadList; begin try try result:=true; ListBoxl.Items.Clear; CloseDataSet; Queryl.SQL.Clear; Queryl.SQL.Add('s elect kod_group, name_group'); Queryl.SQL.Add('from GROUPS'); Queryl.SQL.Add('order by name_group'); Queryl.Open; while not Queryl.EOF do begin ListBoxl.Items.AddObject(Queryl.Fields[1].AsString, TObject(Queryl.Fields[0].AsInteger)); Queryl.Next; end; btnProp.Enabled:=false; btnDelete.Enabled:=false; finally CloseDataSet; end; except end; end; I***********************************************************} { Функция удаления группы из базы данных } *****************^***************************************}
function TfIGroups.DelElement:boolean; begin try result:=true; CloseDataSet; StoredProcl. StoredProcName : = ' del_part__type ' ; StoredProcl.Params.Clear; with StoredProcl.Params.CreateParam (ftlnteger, 'equip_type_id', ptlnput) do begin AsInteger:=integer(ListBoxl.Items.Objects[ListBoxl. Itemlndex]); end; StoredProcl.Prepare; result:=false; end; end;
- 115except result : =false; end; end; / *********************************************************** i { Процедуры, вызываемые из DLL другими модулями i***********************************************************i
}
{ ******** Процедура создания диалогового окна ************} procedure CreateListDlg (Handle: Thandle; p: pointer); begin Application . Handle : =Handle; fl Groups : =TflGroups .Create (Application) ; if assigned(p) then flGroups . Groups : =TGroups (p) ; end; I****************** процедура подключения к БД ************) procedure SetListConnection (const DBHandle : HDBIDB) ; begin flGroups . Databasel . Handle : =DBHandle; end; {******* Процедура загрузки и выгрузки формы списка ********} procedure ShowListDlg; begin with flGroups do begin if LoadList then begin ShowModal ; flGroups . Free; end; end; end; I***********************************************************!
{*********** обработчик нажатия кнопки "Удалить" ***********} procedure TflGroups.btnDeleteClick(Sender:TObject); begin if Application.MessageBox('Удалить группу из базы?', 'Учебные курсы', MB_ICONQUESTION+MB__YESNO) =IDYES then begin if not DelElement then ShowMessage('Ошибка при удалении записи из БД. Код:' +IntToStr(Groups.kod_group));
- 116end; end;
{*********** обработчик нажатия кнопки "Добавить" ***********} {******** Вызывается форма элемента из dlglib01.dll *********} procedure TflGroups.btnAddClick(Sender:TObject); type TCreateElemDlg=procedure(Handle: THandle; pipointer); TSetElemConnection=procedure(const DBHandle:HDBIDB); TShowElemDlg=procedure(const DlgM ode:boolean); var hLib:THandle; CreateElemDlg: TCreateElemDlg; SetElemConnection: TSetElemConnection; ShowElemDlg: TShowElemDlg; PGroups: TGroups; begin hLib:=LoadLibrary('DLGLIB01.DLL'); if hLib < 32 then begin ShowM essage('Отсутствует библиотека'); Exit; end; CreateElemDlg:=TcreateElemDlg(GetProcAddress(hLib, 'CREATEELEM DLL')); SetElemConnection:=TsetElemConnection(GetProcAddress (hlib, 'SETELEM CONNECTION')); ShowElemDlg:=TshowElemDlg(GetProcAddress (hlib, 'SHOWELEM DLG')); PGroups:=TGroups.Create; CreateElemDlg(Application.Handle,PGroups); SetElemConnection(DataBasel.Handle); ShowElemDlg(true); If PGroups.changed then LoadList; FreeLibrary(hlib); end;
(*********** обработчик нажатия кнопки "Свойства" ***********} {******** вызывается форма элемента из dlglib01.dll *********} procedure TflGroups.btnPropClick(Sender:TObject); type TCreateElemDlg=procedure(Handle: THandle; p: pointer); TSetEleraConnection=procedure(const DBHandle: HDBIDB); TShowElemDlg=procedure(const DlgM ode: boolean); var hLib: THandle; CreateElemDlg: TCreateElemDlg; SetElemConnection: TSetElemConnection; ShowElemDlg: TShowElemDlg; PGroups: TGroups; begin hLib:=LoadLibrary('DLGLIB01.DLL'); if hLib < 32 then
{создаем объект для передачи данных в форму элемента} PGroups:=TGroups.Create; with PGroups do begin {в объект вносятся данные из списка - наименование и код} kod_group :=integer (ListBoxl. Items '.Objects [ListBoxl.Itemlndex]); name_group:=ListBoxl.Items[ListBoxl.Itemlndex]; kol_students:=integer(ListBoxl.Items.Obj ects [ListBoxl.Itemlndex]); sredniy_ball:=integer(ListBoxl.Items.Obj ects [ListBoxl.Itemlndex]); end; CreateElemDlg(Application.Handle,PGroups); SetElemConnection (DataBasel.Handle); ShowElemDlg(false); if PGroups.changed then LoadList; FreeLibrary(hLib); end; (************* обработчик нажатия кнопки "Выход" ************} procedure TflGroups.btnExitClick(Sender:TObject); begin if ListBoxl.Itemlndex <> -1 then begin if assigned (Groups) then with Groups do begin kod_group:=integer(ListBoxl.Items.Objects [ListBoxl.Itemlndex]); name_group:=ListBoxl.Items [ListBoxl.Itemlndex]; kol_students:=integer(ListBoxl.Items.Objects [ListBoxl.Itemlndex]); sredniy_ball:=integer(ListBoxl.Items.Objects [ListBoxl.Itemlndex]); end; end; end; end.
Скомпилируйте и постройте оболочку dlglib02.dll.
- 1183.4.3.6.
ОРГАНИЗАЦИЯ ВЫЗОВА ФОРМ Ы СПИСКА в ГЛАВНОМ МОДУЛЕ
Нам осталось создать вызов формы стшска «Группы» в главном модуле main. Перейдите в проект main и создайте обработчик пункта меню «Учебные курсы\Группы»: procedure T fMain.NlOClick(Sender: T Object); type T CreateListDlg=procedure(Handle: T Handle; p:pointer); T SetListConnection=procedure(const DBHandle:HDBIDB); T ShowListDlg=procedure; var nLj_D : 1 Handle ; CreateListDlg: T CreateListDlg; SetListConnection: Т SetListConnection; ShowListDlg: T ShowListDlg; begin hLib:=LoadLibrary('DLGLIB02.DLL') ; if hLib < 32 then begin ShowMessa ge ( ' Отсутствует библиотека DLGLIB02 . DLL ' ) ; Exit; end; CreateListDlg:=T CreateListDlg(GetProcAddress (hLib, 'CREAT ELIST DLL')); SetListConnection:=T SetListConnection(GetProcAddress (hlib, 'SET LIST CONNECT ION') ); ShowListDlg:=T showListDlg(GetProcAddress (hlib,'SHOWLIST DLG')); CreateListDlg(Application.Handle, nil); SetListConnection(fDM.GetSessionHandle) ; ShowListDlg/// (true); FreeLibrary(hlib); end;
Откомпилируйте проект main и запустите программу. Подключитесь к БД и выберите пункт меню «Учебные курсы\Группы». Попробуйте выполнить операции вставки, удаления и изменения данных. Дерево проектной группы к данному моменту содержит четыре проекта (рис. 68).
3.4.3.7.ОБЩАЯ СХЕМА ВЫЗОВА ФОРМ СПИСКА и ЭЛЕМЕНТА Схема создания дилогового окна Группы аналогична схеме создания входного диалога, но отличается наличием каскадного вызова DLLбиблиотеки, т. е. DLL-библиотека вызывается из другой DLL-библиотеки. Ниже приведем схематическое описание работы приложения при выборе пункта меню «Учебный процесс/Группы...»: • запуск приложения; • после выбора пункта меню «Учебный процесс/Группы...»:
- 119-
Рис. 68. Дерево проектной группы > uMain загружает DLL В память: hLib:=LoadLibrary ( ' DLGLIB02 . DLL' ) ;
эта функция возвращает описатель (хэндл) загруженной библиотеки; • после загрузки библиотеки dlglib0l. dll начинается работа с ее экспортируемыми функциями или процедурами: > сначала определяются адреса экспортируемых процедур: CreateListDlg:= TCreateListDlg (GetProcAddres's (hLib, ' CREATELISTDLL ' ) ) ; SetListConnection:= TSetListConnection(GetProcAddress(hLib, 'SETLISTCONNECTION') ) ; ShowListDlg:= TshowListDlg(GetProcAddress(hlib,'SHOWLISTDLG'));
найденные адреса присваиваются специально объявленным в разделе type переменным, имеющим процедурный тип; >- как и в случае с диалогом ввода диалоговое окно отображения списка необходимо сформировать самим. Для этого: - создается диалоговое ОКНО: CreateListDlg:=TcreateListDlg (GetProcAddress (hLib,'CREATELISTDLL'));
- производится подключение к БД: SetListConnection (fDM.GetSessionHandle); при этом диалогу передается тот же handle, полученный из main, подобно эстафетной палочке; - созданное окно отображается для манипуляции с данными из БД, с которой только что связались: ShowListDlg; > возможны четыре варианта манипуляции с данными из БД с помощью вызванного диалога: - при нажатии кнопки «Удалить» вызывается хранимая процедура del groups, которая удаляет из базы выбранную в списке строку;
- 120- при нажатии кнопки «Свойства ...» вызывается DLL-библиотека dlglib01.dll (процесс вызова DLL-библиотеки dlglib01.dll будет описан ниже). В процессе работы DLL-библиотеки dlglib01.dll могут быть вызваны хранимые процедуры get_groups и upd_groups; - при нажатии кнопки «Добавить ...» вызывается DLL-библиотека dlglib01.dll, во время работы которой может быть вызвана хранимая процедура ins_groups; - при нажатии кнопки «Выход» данные из выбранной строки сохраняются в объекте Groups. > после выполнения манипуляций с данными диалоговое окно уничтожается FreeLibrary (hlib) и управление возвращается главному модулю; • работа библиотеки dlglibOl.dll описывается следующим образом: > модуль ulGroups загружает DLL в память hLib:=LoadLibrary ( ' DLGLIBOI . DLL ' ); как и в предыдущем случае эта функция возвращает описатель (хэндл) загруженной библиотеки; >- затем определяются адреса экспортируемых процедур загруженной библиотеки CreateEleraDlg:= TCreateElemDlg(GetProcAddress(hLib,'CREATEELEM DLL')); SetListConnection:= TSetElemConnection(GetProcAddress(hLib,'SETELEM CONNECTION')); ShowElemDlg:= TshowElemDlg(GetProcAddress(hlib, 'SHOWELEM DLG')) ;
найденные адреса присваиваются специально объявленным в разделе type переменным, имеющим процедурный тип; >- создается пустой экземпляр класса PGroups, который должен передаваться в форму элемента PGroups:=TGroups.Create; > создается окно CreateElemDlg (Application. Handle, PGroups); > устанавливается связь с БД SetElemConnection (DataBasel. Handle);
> на экран вызывается форма элемента showElemDlg (true), с помощью которой производятся следущие действия: - если диалог вызван для вставки нового элемента, то с помощью функции insElem вызывается хранимая процедура ins_groups; - если диалог вызван для редактирования элемента, то сначала с помощью функции GetElem вызывается хранимая процедура get_groups, которая производит выборку записи на форму, а затем с помощью функции UpdElem вызывается хранимая процедура upd_groups, которая заменяет отредактированные значения вызванной записи в базе; > после выполнения манипуляций с данными диалоговое окно уничтожается FreeLibrary (hlib) и управление возвращается dlglib02 . dll. Описанная схема приведена на рис. 69.
- 121-
Рис. 69. Схема вызова форм списка и элемента
3.4.4. ДИАЛОГОВЫЕ ОКНА ДЛЯ ТАБЛИЦ STUDENTS, CATHEDRA , TEACHER, SUBJECT, STUDYING, ADVANCING Остальные диалоговые окна для оставшихся таблиц строятся по аналогии. Причем для таблиц Cathedra и Teacher используется каскадный вызов DLLбиблиотек (см. проекты dlglibOl и dlglib02), а для остальных таблиц DLLбиблиотека вызывается с использованием пункта меню. При этом используется схема вызова диалога, описанная при создании формы для подключения к БД (см. проект dll_login).
- 122-
ЗАКЛЮЧЕНИЕ На современном этапе развития технологии машинного моделирования реальной дейс твительности, сфера применения «чистого программирования», когда и данные, и код создаются в пределах одной среды программирования, сужается. На смену этой технологии приходят более сложные технологии моделирования реальной дейс твительности, согласно которым средствами СУБД разрабатываются модели реальной действительнос ти коллективного пользования, а затем, используя ту или иную среду программирования, разрабатываются пользовательские интерфейсы для различных категорий пользователей. Поэтому на современном этапе резко возрастает роль моделирования данных. Следует отметить также резкое усложнение машинных моделей на современном этапе, так как сферой машинного моделирования охватывается все более широкий круг жизнедеятельности человека. Это приводит к увеличению сроков разработки моделей, причем эти сроки становятся сопоставимыми со сроками эксплуатации разработок. В связи с этим становится актуальной проблема сокращения сроков разработок и их адаптируемость к изменяющимся внешним условиям. В создавшихся условиях освоение средств визуальной разработки баз данных, таких как рассмотренное нами CASE-средство ERwin, обеспечивающих по сравнению с разработкой баз данных на основе SQL-запросов существенное сокращение сроков разработки и повышение их надежнос ти, может оказаться весьма полезным для будущих специалис тов. Это поможет им сравнительно легко разрабатывать и поддерживать довольно сложные модели реальной действительности. Весьма ценное качес тво таких средств — масштабируемость разработок. Благодаря этому качеству разработанный код можно легко перенести от одной СУБД к другой, практически не внося в него изменения. В предлагаемом пособии подробно изложены все этапы проектирования базы данных с помощью CASE-средств: создание сущностей предметной области, создание доменов, установка атрибутов сущности, установка связей между сущностями, создание пользовательских свойств, разработка индексов, генераторов, триггеров, хранимых процедур, создание физической модели базы данных и генерация отчетов по разработанной базе данных. Изложение материала сопровождается примером разработки небольшой предметной области.
- 123ПРИЛОЖЕНИЕ А. СПИСОК МАКРОКОМАНД ERWIN Макропеременные, используемые в таблице: <default value>,, — опре деляемый поль зователе м
текст или числовое значение, применяемое при генерации; - SQL-команда, например, INSERT , UPDATE или DELETE; <macro code> - фрагмент макрокода; <predicate> - булево выражение, которое может возвращать значение FALSE или TRUE; <prefix>,
,
~ фрагмент ТСКСТа ИЛИ ЧИСЛОВОС
выражение, которое добавляется перед именем таблицы или колонки при генерации; <separator> - разделитель, который вставляется в текст триггера или процедуры при генерации (заключается в двойные кавычки);
, <default name>, <domain name>, - ИМЯ таб-
лицы, значения по умолчанию, домена или правила валидации; - переменная, использующаяся в триггере. Макрокоманд Описание а Оператор несравнения, ! =, возвращает TRUE, если аргу%!=(<macro codel>, <macro code2>) %%
(<macro codel>,
менты macro codel И macro code2 НС равны
Два символа % необходимо использовать, если расширенный текст триггера должен содержать один символ %
Описание Возвращает имя команды, до или после которой срабатывает триггер, например, INSERT , UPDATE или DELETE Возвращает список команд, до или после которых срабатывает триггер, например, INSERT, UPDATE или DELETE Выполняет операцию «И» над булевыми предикатами, заданными в macro codel и macro code2 Возвращает тип данных текущего атрибута Возвращает определение атрибута Возвращает имя значения по умолчанию, связанное с атрибутом Возвращает имя домена, связанное с атрибутом Возвращает имя колонки, соответствующей атрибуту Возвращает целое число, представляющее длину типа данных текущего атрибута, например varchar ( 2 0 ) ->2 0 Возвращает ID атрибута Булев предикат, который может быть использован как условие в выражении %if . Он определяет, в ходит ли те: кущий атрибут в состав внешнего ключа Булев предикат, который может быть использован как условие в выражении % If . Он определяет, является ли текущий атрибут именем роли Булев предикат, который может быть использован как условие в выражении %if . Он определяет, в ходит ли текущий атрибут в состав первичного ключа Возвращает логическое имя текущего атрибута Возвращает строку, представляющую режим нулевых значений для текущего атрибута Возвращает физический тип данных текущего атрибута независимо от того, является ли этот тип данных типом данных, определенным пользователем Выдает список всех атрибутов сущности триггера, выполняя заданную функцию для каждого элемента Возвращает имя правила валидации, связанного с данным атрибутом; может быть использован в ForEachFKAtt ИЛИ ForEachAtt
Возвращает мощность (кардинальность) связи Возвращает физическое имя таблицы дочерней сущности связи Возвращает список всех атрибутов дочерней сущности в связи, выполняя заданную функцию для каждого элемента Возвращает список внешних ключей дочерней сущности в связи, выполняя заданную функцию для каждого элемента
- 125Макрокоманда
Описание Возвращает список внешних ключей дочерней сущности Генерирует раздельный список функций для всех неключевых атрибутов дочерней сущности в связи, выполняя ф список неключевых атрибутов Возвращает дочерней сущности связи с их типами данных
Возвращает список атрибутов дочерней сущности в связи с их типами данных (см. %ParamDecl) Генерирует раздельный список функций для каждого элемента первичного ключа дочерней сущности, выполф %CildPKDecl Возвращает список атрибутов первичного ключа (, , <separator>) ней сущности в связи с их типами данных (см. %Concat (, : Производит конкантенацию и . Воз : вращает результат % Cur rent Database Возвращает имя БД, которое используется в диалоге %CurrentFile Возвращает имя файла модели ( . ER1), на основе которой % Cur rent Server Возвращает имя сервера, для которого генерируется %CurrentUser ; Возвращает имя пользователя, которое используется в %CurrentTriggerDef aultЧасть триггера, определенного пользователем default Body body, которая содержится в diagram-wide-сегменте шаблона CUSTOM TRIGGER FOOTER %CurrentTriggerDef ault- i Часть триггера, определенного пользователем default Footer footer, которая содержится в diagram-wide-сегменте шаблона CUSTOM TRIGGER FOOTER % Cur rent Trigger DefaultЧасть триггера, определенного пользователем default Header header, которая содержится в diagram-wide-сегменте шаблона CUSTOM TRIGGER HEADER %DatatypeName ( } Возвращает тип данных IDatatypeScale ( ) Для десятичных типов данных возвращает разряд числа %DatatypeWidth() : Возвращает ширину поля %Datatime Возвращает строку, представляющую текущую дату и %DBMS Возвращает имя СУБД %DBMSDelim Возвращает разделитель операторов СУБД %Decl (<arg>, как переменную и, если это задано, value>) присваивает ей значение j
- 126Макрокоманда
Описание Возвращает имя по умолчанию Возвращает значение по умолчанию Возвращает физический тип данных домена
Возвращает определение домена Возвращает имя домена Возвращает режим нулевых значений для домена ;
(NULL/NOT NULL)
Возвращает имя правила валидации, связанное с доменом Возвращает ID сущности или таблицы Возвращает имя сущности или таблицы Макрокод записывается в файл Задает, когда срабатывает триггер Расширяет макрокод для каждого из атрибутов заданной таблицы Расширяет для каждой связи, в которой сущность триггера является дочерней Расширяет макрокод для каждого значения по умолчанию Расширяет макрокод для каждого домена Расширяет макрокод для каждой сущности Расширяет макрокод для каждого из атрибутов внешнего ключа, мигрировавших через текущую связь Расширяет макрокод для каждого индекса в подмножестве модели Расширяет макрокод для каждого члена индекса в подмножестве модели Расширяет макрокод для всех инвертированных входов и альтернативных ключей в подмножестве модели
Описание Расширяет макрокод для всех членов ключей
Расширяет для каждой связи, в которой сущность триггера является родительской Расширяет макрокод для всех значений правила валидации Расширяет макрокод для всех правил валидации В зависимости от условия, расширяет макрокод i f или else. Часть е1se не является обязательной Позволяет включать макрокоды триггера в файлы Возвращает имя индекса Возвращает тип индекса Часть условия поиска where, присоединяющая внешний ключ дочерней сущности к первичному ключу родительской сущности связи Часть условия поиска where, соединяющая первичные ключи двух корреляций или таблицы и корреляции Возвращает имя ключа Возвращает длину строки <macro code> Преобразует аргумент <macro code> в нижний регистр Возвращает максимальное значение - или Возвращает минимальное значение -< value 1> или
Возвращает список всех неключевых атрибутов сущности триггера, выполняя заданную функцию для каждого Возвращает список неключевых атрибутов сущности триггера с их типами данных (см. %ParamDecl) Выполняет операцию «логическое НЕ» над булевым предикатом, определенным в <macro code> Часть условия поиска where, сравнивающая внешний ключ дочерней сущности с null. Эта макрокоманда расширяется тогда и только тогда, когда связь является неидентифицирующей, nulls allowed
Описание Выполняет операцию «логическое ИЛИ» над булевыми предикатами, определенными в <macro codel> и <macro code2> Выдает список всех атрибутов триггера с их типами данных. Имя каждого атрибута имеет формат: . Если заданы и старый, и новый префикс, то длина списка удваивается. В первой половине списка содержится , a во второй - Присваивает значения параметрам процедур, заданным в и/или в для всех атрибутов сущности Физическое имя таблицы родительской сущности связи Расширяет любую макрокоманду атрибута (например, %AttFieldName, %AttDatatype) для атрибута родительского первичного ключа, который, мигрировав, ф Возвращает список всех атрибутов родительской сущности в связи, выполняя заданную функцию для каждого Возвращает список всех неключевых атрибутов родительской сущности в связи, выполняя заданную функцию Возвращает список неключевых атрибутов родительской сущности связи с их типами данных (см. %ParamDecl) Возвращает список неключевых атрибутов родительской сущности в связи с их типами данных (см. %ParamDecl) Выдает список атрибутов РК родительской сущности свяф Возвращает список атрибутов первичного ключа родительской сущности связи с их типами данных (см. %РаВозвращает физическое имя связи Выдает список атрибутов РК родительской сущности Возвращает список атрибутов первичного ключа сущности триггера с их типами данных (см. %ParamDecl) Возвращает ID связи Проверяет null-выражение для связи и возвращает TRUE, NULL правило ссылочной целостности Возвращает
129Макрокоманда
Описание Расширяет код шаблона, присоединенного к текущей связи. Если нет присоединенного кода, то расширяется Возвращает тип связи Выдает список атрибутов внешнего ключа дочерней сущности связи, в котором каждому элементу присвоено заВыдает список атрибутов первичного ключа заданной таблицы, в котором каждому элементу присвоено заданЗаменяет строку <parent>B строке на строку <substitute> Создает подстроку для расширения заданного <macro code>
%RelT emplate
%RelT ype %SetFK(, ) %SetPK(
, )
%Substitute (, <parent>, <substitute>) %Substr (<macro code>, , ) %Switch (<argument>) {% Choose (
Позволяет расширить макрокод по условию
''
Возвращает физическое имя таблицы сущности триггера Возвращает имя шаблона триггера, хранимой процедуры или скрипта; может быть использовано в редакторе Entity Trigger Возвращает физическое имя триггера Булев предикат, принимающий значение TRUE, если заданный триггер и связь относятся к заданному действию
%T able Name %T emplate Name
IT rigger Name %T riggerRelRI (, , )
(Update\Delete\Insert) , типу (ChildX Parent) и %UpdateChildFK() %UpdateParentPK( )
Выдает список внешнего ключа дочерней сущности свяВыдает список первичного ключа родительской сущности связи, выполняя функцию update для каждого элеВыдает список первичного ключа сущности триггера, Преобразует аргумент <macro code> в верхний регистр Возвращает TRUE, если заданное правило валидации <arg> имеет допустимые значения, иначе FALSE Возвращает имя правила валидации Возвращает правило валидации для сервера; может быть использовано в любом месте с аргументом или в рамках действия правила, без аргументов
- 130Макрокоманда
Описание
%ValidValue %ValidValueDef %VerbPhrase
:
Возвращает значение допустимого значения; используетВозвращает определение допустимого значения; испольВозвращает глагольную фразу связи
- 131ПРИЛОЖЕНИЕ В. ТРЕБОВАНИЯ ПО ВЫПОЛНЕНИЮ ПОЯСНИТЕЛЬНОЙ ЗАПИСКИ Пояснительная записка должна включать разделы: 1. Анализ предметной области и описание концептуальной структуры БД. В данном разделе необходимо описать процессы выделения сущностей и установки связей между ними. Выделение сущностей и установление связей между ними должно проводиться с использованием методики нормализации данных в БД. 2. Описание процесса создания логической структуры БД с помощью CASEсредства ERwin по спроектированной выше концептуальной структуре. В этом разделе нужно обосновать вводимые домены, описать и обосновать типы и характеристики связей между сущностями. Необходимо также привес ти описания генераторов, триггеров и хранимых процедур. Описания сопровождать текс тами генераторов, триггеров и хранимых процедур на макроязыке ERwin и на языке запросов SQL. 3. Описание процесса разработки пользовательских форм. Перед разработкой форм провести анализ деятельнос ти пользователя при работе с вашей БД, т. е. вы должны разработать алгоритм действий пользователя и предложить ему максимум удобств при работе с формой (например, везде, где это только возможно, данные должны не набираться, а выбираться из выпадающего списка). Элементы ввода/вывода должны располагаться в порядке ввода информации, должны быть определенным образом выравнены. 4. Разрабатываемые отчеты должны соответс твовать по форме реально существующим документам. Для этого вы должны оформлять их в соответствии с существующими нормативами и шаблонами. 5. В приложении привести распечатки скрипта для создания БД текс та программ для создания пользовательских форм и отчета (если отчет создается с ПОМОЩЬЮ серверов Автоматизации).
Использвание фрагментов нас тоящего пособия в Пояснительной записке не допускается. По каждому из разделов должно быть не менее 5-6 страниц текс та (без учета рисунков).
- 132ПРИЛОЖЕНИЕ С. ВАРИАНТЫ ЗАДАНИЙ ПО КУРСОВОЙ РАБОТЕ С.1. ОБЩЕЕ ЗАДАНИЕ ДЛЯ ВСЕХ ВАРИАНТОВ Разработка БД на заданную тему на серверной СУБД InterBase (локальная версия) и клиентского приложения для сформированной БД для ввода необходимых данных, а также их просмотра, добавления и удаления. • выполнить анализ предметной области; • разработать объекты для моделирования данной предметной области в СУБД InterBase;
• разработать домены для реализации объектов БД с помощью CASЕ-средства ERwin;
• реализовать разработанные объекты с помощью CASE-средства ERwin; • реализовать с помощью ERwin связи между объектами модели; • разработать генераторы и триггеры для автоматизации выполнения типовых операций (должны быть как минимум по одному генератору и триггеру); • разработать хранимые процедуры для вставки, изменения и удаления записей из БД; • разработать индексы для ускорения поиска необходимых данных БД; • сгенерировать SQL-сценарий для последующей генерации физической модели БД ДЛЯ СУБД InterBase. • разработать оболочку приложения; • разработать набор библиотек DLL, которые обеспечивают доступ к БД; • создать объекты, соответствующие заданным объектам БД; • создать типовые формы для ввода элементов (или просмотра списка элементов) заданного фрагмента БД. Поместить разработанные формы в репозитарий; • на основе типовых форм из репозитария создать формы для ввода элементов (или просмотра списка элементов) заданного фрагмента БД.
- 133C.2. ВАРИАНТЫ ПРЕДМЕТНЫХ ОБЛАСТЕЙ Вариант 1 — Отобразить в БД сведения о месячной зарплате рабочих и средней зарплате по цехам за изготовление деталей. Деталей должно быть ≈15 видов, изготовление которых имеет определенную стоимость. Должны быть отражены сведения о следующих атрибутах ПрдО: > Фамилия рабочего; > Имя рабочего; > Отчество рабочего; > Номер цеха, где работает рабочий; > Название цеха; > Начальник цеха; > Средняя зарплата по цеху; > Размер заработной платы рабочего за изготовленные детали; > Разряд (учесть разрядные надбавки при подсчете зарплаты); > Дата поступления на работу; > Ассортимент деталей с указанием наименования и стоимости изготовления; > Перечень изготовленных деталей с указанием рабочего, изготовившего деталь. Вариант 2 — Учет изделий, собранных в цехе изделий за неделю с указанием объема сборки и ее стоимости за каждый день. Должны быть отражены сведения о следующих атрибутах ПрдО: > Фамилия сборщика; > Имя сборщика; > Отчество сборщика; > Разряд (при расчете стоимости сборки изделий учесть надбавку за разряд); > Стаж работы (при расчете с тоимости сборки изделий учесть надбавку за стаж); > Стоимость собранных изделий за каждый день недели; > Количество собранных изделий за каждый день недели; > Ассортимент изделий с указанием наименования и стоимости их сборки; > Перечень изготовленных изделий с указанием сборщика и дня недели изготовления.
- 134Вариант 3 - Учет изделий категорий А, В, С, D, Е, собранных в цехе за месяц с указанием количества изделий каждой категории и стоимости их сборки. Должны быть отражены сведения о следующих атрибутах ПрдО: > Фамилия сборщика; > Имя сборщика; > Отчество сборщика; > Разряд (при расчете стоимости сборки изделий учесть надбавку за разряд); > Стаж работы (при расчете стоимости сборки изделий учесть надбавку за стаж); > Количество изделий каждой категории, собранных за месяц; > Стоимос ть сборки изделий каждой категории, собранных за месяц с учетом квалификации и стажа работы сборщика; > Ассортимент категорий изделий (А, В, С, D, E) с указанием наименования и стоимости их сборки; > Перечень изготовленных изделий с указанием сборщика и категории изделия. Вариант 4 — Сведения об абонентах АТС с учетом разницы междугородних и обычных переговоров. При расчете платы за услуги должны учитываться льготы и тип установки. Должны быть отражены сведения о следующих атрибутах ПрдО: > Фамилия; > Имя; > Отчество; > Адрес; > Год установки телефона; > Тип установки телефона (спаренный или нет: оплата спаренного телефона составляет 60 % от обычного); > Льгота (50 % процентов скидки при оплате); > Стоимос ть абонентской платы; > Стоимость междугородних разговоров; > Общая сумма с учетом льгот и типа установки; > Расценка междугородних разговоров (≈15 записей) с указанием города, стоимости за минуту разговора; > Перечень междугородних разговоров с указанием ФИО абонента, города, длительности разговора в минутах и стоимости разговора; > Номер телефона абонента.
- 135-
Вариант 5 — Сведения о наличии игрушек каждого вида, количестве поступлений и реализации игрушек каждого вида и суммы выручки за их реалиизацию в магазине. Должны быть отражены сведения о следующих атрибутах ПрдО: > Название игрушки; > Количесво игрушки на складе; > Количество поступлений каждого вида игрушки за месяц; > Продано каждого вида игрушки за месяц; > Вырученная сумма за реализацию каждого вида игрушки за месяц; > Ассортимент игрушек с указанием цены, завода-изготовителя, города, где находится завод; > Перечень игрушек с указанием даты изготовления игрушки, даты пос тупления в магазин и даты реализации. Вариант 6 — Результаты сессии на первом курсе кафедры XX. Должны быть отражены сведения о следующих атрибутах ПрдО: > Фамилия студента; > Имя студента; > Отчество студента; > Пол; > Семейное положение; > Средний балл за сессию; > Живет в общежитии или нет (1 - живет, 0 - не живет); > Индекс группы; > Сдаваемые дисциплины (пять дисциплин) с указанием наименования, ФИО преподавателя, ученой степени преподавателя, ученого звания преподавателя, числа прослушанных лекций; > Ведомости по пяти экзаменам с указанием дисциплины, ФИО студента, оценки за экзамен. Вариант 7 — Сведения о состоянии книжного фонда библиотеки. Должны быть отражены сведения о следующих.атрибутах ПрдО: > Шифр книги; > Кому выдана книга; > Дата выдачи книги; > Дата возврата книги; > Дата поступления книги в библиотеку; > Наличие книг данного наименования на полках; > Всего выдано книг данного наименования читателям;
- 136> Перечень книг с указанием автора, наименования, издательства, года издания, стоимости книги, тематического раздела, к которому относится книга; > Сведения о читателях, с указанием ФИО, года рождения, адреса, телефона (домашнего и рабочего), количества книг, выданных ему. Вариант 8 ~ Сведения о рейсах авиакомпании за неделю с указанием числа проданных билетов и суммы выручки за каждый день недели. Должны быть отражены сведения о следующих атрибутах ПрдО: > Номер рейса; > Пункт назначения; > Время вылета; > Время прибытия; > Время в пути; > День недели, в который выполняется полет (1, 2, 3, 4, 5, 6, 7); > Тип самолета; > Вмес тимость самолета (2-, 3-местные); > Количество свободных мест; > Перечень выполненных маршрутов за неделю; > Число проданных билетов за каждый день недели; > Сумма выручки за каждый день недели; > Сведения о пассажирах с указанием ФИО, паспортных данных, номера рейса. Вариант 9 - Сведения о работе обувного магазина. Должны быть отражены сведения о следующих атрибутах ПрдО: > Ассортимент товара с указанием наименования обуви, фабрикиизготовителя, цены товара; > Перечня товара, поступившего в магазин, с указанием наименования товара, количества пар, размера, даты поступления, даты продажи; > Сведения о наличии товара в магазине с указанием номера товара по ассортименту, количества товара на складе, размера обуви, продано товара за текущий месяц, сумма реализации по каждому виду обуви конкретного размера. Вариант 10 — Сведения о результативности нападающих хоккейных команд «Спартак», «Торпедо» и «Динамо» за время турнира этих команд по круговой системе (каждая команда играет с каждой по две игры: в одной игре команда принимает у себя, т. е. является «хозяином», в другой играет в гостях). Должны быть отражены сведения о следующих атрибутах ПрдО: > Фамилия; > Имя;
- 137> Команда;
> Дата приема в команду; > Количество сыгранных матчей; > Число заброшенных шайб каждой командой; > Забитые голы с указанием ФИО забившего, ФИО автора голевой передачи, в какой игре забит гол и в какое время; > Расписание игр с указанием команды-хозяина и команды гостя, даты и времени проведения игры, результата игры; > Количество голевых передач; > Штрафное время; > Результаты турнира, где должны быть указана команда, общее число набранных очков (за победу - 3 очка, за ничью - 1 очко, за поражение - 0 очков), количество побед, количество ничьих, количество поражений, общее число забитых голов и общее число пропущенных шайб. Вариант 11 — Сведения о выборе дисциплин студентами пяти групп. Каждый студент должен выбрать по три дисциплины. Должны быть отражены сведения о следующих атрибутах ПрдО:
> Фамилия; > Имя; > Отчество; > Номер зачетной книжки; > Живет ли в общежитии (живет - 1; не живет - 0); > Первая выбранная дисциплина; > Вторая выбранная дисциплина; > Третья выбранная дисциплина; > Индекс группы; > Пять дисциплин (желает изучать - 1, не желает изучать - 0); > Сведения о пяти дисциплинах с указанием наименования, ФИО преподавателя, числа теоретических занятий, числа практических занятий; > Сведения о выбранных дисциплинах студентами каждой группы (не менее трех групп), с указанием количества студентов, выбравших каждую из дисциплин; > Средний балл студента. Вариант 12 - Журнал регистрации расходов и доходов в бухгалтерии за оказанные услуги по каждому виду уcлуг. Должны быть отражены сведения о следующих атрибутах ПрдО:
> Ассортимент услуг с указанием наименования, стоимости, суммы рас-
- 138ходов, процента прибыли; > Список исполнителей фирмы с указанием ФИО, квалификации, оплаты за услуги в зависимости от квалификации за месяц; > Перечень оказанных услуг, где должны быть указаны вид услуги, заказчик услуги, дата выполнения услуги, исполнитель; > Список фирм-заказчиков, где должны быть указаны название, адрес, место нахождения фирмы; > Журнал регистрации расходов и доходов за месяц с указанием по каждому виду услуг суммы расходов (расходов по виду услуг плюс оплата исполнителя в зависимости от квалификации), суммы прибыли. Вариант 13 - Демографический анализ региона. Должны быть отражены сведения о следующих атрибутах ПрдО: > Регион; > Рождаемость на 1 тыс. человек; > Смертность на 1 тыс. человек; > Численность в млн. человек; > Количество работающих людей в млн.; > Количество безработных в млн. Вариант 14 — Учет оптовых продаж. Должны быть отражены сведения о следующих атрибутах ПрдО: > Ассортимент товаров с указанием наименования товара, завода изготовителя, цены товара; > Список фирм-изготовителей товаров и оптовых покупателей, с указанием наименования фирмы, адреса фирмы; > Перечень оптовых покупок с указанием фирмы покупателя, вида товара, даты покупки, размера партии, стоимости покупки; > Сведения о состоянии оптовой фирмы с указанием наличия на складе каждого вида товара, суммы реализации товара по каждому виду. Вариант 15 - Учет лекарств в оптовом магазине. Должны быть отражены сведения о следующих атрибутах ПрдО: > Ассортимент лекарств с указанием наименования лекарс тва, названия фирмы-изготовителя, адреса фирмы-изготовителя, стоимости; > Список аптек, которым отпускаются лекарства, с указанием названия, адреса, ФИО руководителя; > Перечень отпущенных аптекам лекарств с указанием наименования лекарства, названия аптеки, размера партии, даты продажи, даты изготовления, срока годности;
- 139> Сведения о продаже лекарств оптовым магазином по каждому виду лекарств с указанием наличия в магазине, количества реализованного товара, стоимости. Вариант 16 — Сведения о размещении спортсменов, прибывших на соревнование, в гостиницах. Должны быть отражены сведения о следующих атрибутах ПрдО:
> Список спортсменов с указанием ФИО, вида спорта, классификации; > Размещение спортсменов в гостинице с указанием ФИО спортсмена, название гостиницы, где он размещен, тип номера (1-, 2-, 3-местный); > Перечень гостиниц города с указанием названия, наличия общего количества мест, числа 1-, 2-, 3-местных номеров, числа свободных мест в 1-, 2-, 3-местных номерах, общее число размещенных в гостинице спортсменов. Вариант 17 - Сведения об участниках конкурса бальных танцев. Должны быть отражены сведения о следующих атрибутах ПрдО:
> Список танцоров, участвующих в соревновании, с указанием ФИО, города (каждый выставляет одинаковое число представителей), возрастной группы; > Расписания проведения соревнований с указанием ФИО партнера, ФИО партнерши, номера пары, даты выступления, набранных баллов; > Итоговая таблица выступлений, где подсчитывается суммарные баллы для каждого города по итогам выступлений представителей городов, занимаемое место. Вариант 18 - Учет рождаемости в роддоме. Должны быть отражены сведения о следующих, атрибутах ПрдО:
> Список матерей, находящихся в роддоме, с указанием ФИО, года рождения, адреса, даты поступления, пола ребенка, состояния здоровья ребенка, даты рождения, времени рождения, даты выписки, номера палаты; > Списка врачей с указанием ФИО, номера палаты; > Учет состояния роддома в течение месяца с указанием числа родившихся мальчиков, числа родившихся девочек, общего числа родившихся малышей, числа здоровых малышей, числа больных малышей. Вариант 19 — Городские соревнования по теннису. Должны быть отражены сведения о следующих атрибутах ПрдО: > Фамилия спортсмена; > Имя спортсмена; > Отчес тво спортсмена;
- 140> Возраст спортсмена; > Пол; > Рост; > Набранные очки; > Информация о графике проведения соревнований, где указывается играющие пары игроков, дата, время и поле проведения соревнований, результат игры; > Пять полей (города) с рейтингом; > Результирующая таблица соревнования с указанием названий команд, ФИО тренера, фирма-хозяин команды, количества набранных ими очков, занятого места. Вариант 20 - Сведения о слушателях на курсах повышения квалификации. Должны быть отражены сведения о следующих атрибутах ПрдО: У Фамилия слушателя; > Имя; > Отчество; > Пол; > Должность; > Оценки по прослушанным дисциплинам (маркетинг, финансы и кредит); > Расценки за обучение, где указывается вид занятий (чтение лекций, прием экзаменов, выдача диплома), стоимость каждого из видов обучения; > Название и тип организации, из которой прибыл слушатель (коммерческая, государственная и т. д.), адрес организации; > Оплата обучения с указанием названия организации, общего числа слушателей от организации, числа успешно сдавших экзамен, всего выплачено организацией за обучение. Вариант 21 — Сведения о зарплате преподавателей кафедры. Должны быть отражены сведения о следующих атрибутах ПрдО: > Фамилия преподавателя; > Имя преподавателя; > Отчес тво преподавателя; > Ученая степень преподавателя и ученое звание преподавателя, зарплата преподавателя с учетом оклада, доплаты за ученую степень и за ученое звание; > Читаемая дисциплина; > Надбавка за степень (д-р техн. наук- 1500 и канд. техн. наук - 900 руб.); > Надбавка за звание (профессор - 50% от оклада, и доцент - 40% от оклада);
- 141> Оклады преподавателей в зависимости от степени, звания (д-р техн. наук, проф. - разр 17, 2500 руб; д-р техн. наук, доц. - разр 16, 2000 руб; канд. техн. наук, доц. -разр 15, 1800 руб; канд. техн. наук, без звания, -разр 14, 1400 руб. Вариант 22 — Учет поступления больных в больницу. Должны быть отражены сведения о следующих атрибутах ПрдО: > Фамилия больного; > Имя; > Отчес тво; > Пол; > Дата рождения; > Дата поступления; > Дата выписки; > Диагноз; > ФИО лечащего врача; > Ученая степень врача; > Ученое звание врача; > Степень тяжести состояния больного; > Специальность (отделение); > Сведения по больнице за неделю по отделениям, в том числе: число поступивших, число выписанных. Вариант 23 - Учет призывников в военкомате. Должны быть отражены сведения о следующих атрибутах ПрдО: > Фамилия призывника; > Имя; > Отчество; > Год рождения; > Адрес; > Образование; > Дата прохождения медкомиссии; > Состояние здоровья (годен, не годен); > Семейное положение; > Места направления призывников: номер воинской час ти (не менее 15), наименование вида войск, место дислокации воинской части, требуется призывников для укомплектования части; > Сведения о направлении призывников по видам войск: всего направлено, требуется направить по плану, процент выполнения призыва.
- 142Вариант 24 - Учет золотых изделий в ювелирном магазине. Должны быть отражены сведения о следующих атрибутах ПрдО: > Ассортимент изделий, где указывается вид изделия, вес, проба драгметалла, стоимость; > Изделия, поступившие в магазин, где указывается вид изделия, мастеризготовитель, дата изготовления, дата поступления, дата реализации, адрес мастера-изготовителя, стаж работы, разряд (1, 2, 3, 4, 5); > Сведения о реализации изделий в магазине за месяц по видам изделий, где указывается: количес тво изделий данного вида в магазине, продано изделий данного вида в магазине, сумма выручки за продажу изделий данного вида в магазине.
- 143БИБЛИОГРАФИЧЕСКИЙ СПИСОК
1. Бекаревич,Ю. Б. Самоучитель Microsoft Access 2000 / Ю. Б. Бекаревич, Н. В. Пушкина. - СПб.: БХВ - Санкт-Петербург, 1999-480 с. 2. Маклаков,С. В. BPwin и ERwin. CASE-средства разработки информационных систем / С. В. Маклаков. - М.: Диалог - МИФИ, 1999. - 256 с. 3. Кандзюба,С. П. Delphi 5. Базы данных и приложения: Лекции и упражнения / С. П. Кандзюба, В. Н. Громов. - К.: Издательс тво «ДиаСофт», 2001. - 592 с. 4. Корнеев, В. В. Базы данных. Интеллектуальная обработка информации / В. В. Корнеев, А. Ф. Гареев, С. В. Васютин, В. В. Райх. - М.: «Нолидж», 2000. 352 с. 5. Базы данных: модели, разработка, реализация / Т. С. Карпова. - СПб.: Питер, 2001. - 304 с. 6. Хансен,Г. Базы данных: разработка и управление / Г. Хансен, Дж. Хансен. - Пер. с англ. - М.: ЗАО «Издательство БИНОМ», 1999. - 704 с.
Учебное издание ТОКМАКОВ Геннадий Петрович БАЗЫ ДАННЫХ И ЗНАНИЙ Проектирование баз данных по технологии «клиент-сервер» и разработка клиентских приложений Учебное пособие Редактор М. В. Теленкова Подписано в печать 20.07.2005. Формат 60x84/16. Усл. печ. л. 8,37. Уч.-изд. л. 8,00. Тираж 100 экз. Заказ 1048. Ульяновский государственный технический университет 432027, г. Ульяновск, ул. Сев. Венец, 32. Типография УлГТУ. 432027, г.Ульяновск, ул. Сев. Венец, 32.