При выборе первичного ключа предпочтение
должно отдаваться наиболее простым ключам.
Атрибуты первичного ключа не должны содержать
нулевых значений. Значения ключевых атрибутов
не должны меняться в течение всего времени
существования экземпляра сущности. Кроме
этого, каждая сущность должна иметь, по
крайней мере, один потенциальный ключ.
Некоторые сущности могут иметь более
одного возможного ключа. При выборе одного
из них первичным остальные становятся
альтернативными ключами (Alternate key).
При работе информационной системы
нередко необходим доступ сразу
к нескольким экземплярам сущностей.
1.2 Генерация системного каталога
Генерация системного каталога выполняется
после создания физической модели информационной
системы [2].
Для генерации системного каталога
БД следует выбрать в ERwin пункт
меню Tasks/Forward Engineer/Schema Generation или нажать
на кнопку
на панели инструментов.
Появляется диалог Schema Generation (рисунок
4), позволяющий задать набор установок,
определяющих, какие элементы должны войти
в схему БД.
Для каждой логической схемы можно
создать несколько таких наборов установок
(опций). Текущий набор установок выбирается
в списке Option Set, в верхней части диалогового
окна.
Для создания нового набора установок
нажмите клавишу New и введите
имя создаваемого набора.
Закладки диалога Schema Generation.
Options. Служит для задания опций генерации
объектов БД - таблиц, колонок, индексов,
представлений и т.д. Для задания опций
генерации какого-либо объекта следует
выбрать название объекта в левом списке
закладки, после чего включить необходимые
опции в правом списке.
В закладке Summary
отображаются все опции, заданные в закладке
Options.
Comment. Позволяет
внести комментарий для каждого набора
опций.
Кнопки диалога Schema Generation.
Рисунок 4 - диалог Schema Generation
Filter. Вызывается фильтр таблиц. Здесь
выбираются таблицы (сущности), которые
должны войти в схему. Диалоговое окно
фильтра состоит из двух списков, содержащих
имена таблиц или сущностей, в зависимости
от положения переключателя Display Names. В
левом списке находятся имена таблиц,
исключенные из схемы генерации, в правом
- вошедшие в схему. Перемещение таблиц
между списками осуществляется при помощи
стандартных кнопок со строками. Относительное
количество выбранных таблиц показано
над правым списком в виде дроби, в знаменателе
которой проставляется общее число таблиц
в схеме. Эта же дробь выводится и в нижней
части главного окна генератора схем.
Preview - просмотр сгенерированного
SQL-сценария БД. Диалог содержит стандартное
текстовое окно и набор кнопок для редактирования,
просмотра и печати текста сценария. В
полученном сценарии присутствуют различные
SQL-запросы:
CREATE TABLE - создание
таблицы;
CREATE INDEX - создание
индекса;
ALTER TABLE... ADD PRIMARI KEY
- добавление первичного ключа;
ALTER TABLE... ADD FOREINGN
KEY - добавление внешнего ключа и т.д.
Print - вывод SQL-сценария
на печать.
Report - Сохранение
SQL-сценария (скрипта) в текстовом файле.
Эти команды можно в дальнейшем редактировать
текстовым редактором и выполнять при
помощи соответствующей утилиты сервера.
Generate - запуск процесса
генерации физической схемы БД. В диалоге
связи с БД необходимо ввести имя пользователя
и пароль. В выпадающем списке Database следует
выбрать имя ODBC-драйвера. После нажатия
кнопки Connect появится диалог Generate Database
Schema. По умолчанию в диалоге установлена
опция Stop If Failure. Это означает, что при первой
же ошибке выполнение скрипта прекращается.
Щелкнув по кнопке Continue, можно продолжить
выполнение. Кнопка Abort прерывает выполнение.
При выключенной опции Stop If Failure скрипт
будет выполняться, несмотря на встречающиеся
ошибки.
Замечание: перед выполнением этапа
генерации физической схемы необходимо
быть уверенным в том, что БД создана и
"пуста". Если полной уверенности
в этом нет, то рекомендуется выполнить
в WISQL следующие действия:
- соединиться с БД (Connect to Database);
- удалить БД (Drop Database);
- создать БД (Create Database);
- отсоединиться от БД (Disconnect from Database);
- перейти в ERwin.
Разумеется, эту последовательность
шагов можно выполнять лишь на
этапе изучения методики прямого
проектирования, то есть, когда нет
необходимости сохранять объекты
старой БД. При создании новой БД
важно сохранить неизменным ее имя.
Это позволит работать с одним и тем же
ODBC-драйвером.
ПРАКТИЧЕСКАЯ
ЧАСТЬ
В рамках данной курсовой работы
было выполнено построение логической
и физической моделей БД. Модели представлены
на рисунках 5 и 6 соответственно.
Рисунок 5 – Логическая модель БД
Рисунок 6 – Физическая модель
БД
СКРИПТ-ГЕНЕРАЦИЯ СХЕМЫ БД
CREATE TABLE Адрес_участка
(
Кадастровый_номер CHAR(18) NOT
NULL ,
Индекс VARCHAR2(20)
NULL ,
Район CHAR(18) NOT NULL ,
Населенный_пункт
CHAR(18) NOT NULL ,
Улица CHAR(18)
NOT NULL ,
Дом VARCHAR2(20) NULL
);
CREATE UNIQUE INDEX XPKАдрес_участка ON Адрес_участка
(Кадастровый_номер ASC);
ALTER TABLE Адрес_участка
ADD CONSTRAINT XPKАдрес_участка
PRIMARY KEY (Кадастровый_номер);
CREATE TABLE Документ
(
ИД_документа CHAR(18) NOT NULL ,
Серия_и_номер
VARCHAR2(20) NULL ,
Тип_документа INTEGER NULL ,
Когда_выдан DATE NULL ,
Кем_выдан VARCHAR2(20)
NULL
);
CREATE UNIQUE INDEX XPKДокумент ON Документ
(ИД_документа ASC);
ALTER TABLE Документ
ADD CONSTRAINT XPKДокумент
PRIMARY KEY (ИД_документа);
CREATE TABLE Запрос_в_росреестр
(
ИД_запроса
VARCHAR2(20) NOT NULL ,
Заявление_запроса
INTEGER NOT NULL ,
СНИЛС VARCHAR2(20) NULL
);
CREATE UNIQUE INDEX XPKЗапрос_в_росреестр ON
Запрос_в_росреестр
(ИД_запроса ASC);
ALTER TABLE Запрос_в_росреестр
ADD CONSTRAINT XPKЗапрос_в_росреестр
PRIMARY KEY (ИД_запроса);
CREATE TABLE Заявитель
(
ИД_Заявителя INTEGER NOT NULL ,
Фамилия CHAR(18) NULL ,
Имя VARCHAR2(20) NULL ,
Отчество VARCHAR2(20)
NULL ,
Документ_заявителя CHAR(18) NOT
NULL ,
Район CHAR(18)
NOT NULL ,
Населенный_пункт CHAR(18) NOT NULL ,
Улица CHAR(18) NOT NULL ,
Дом VARCHAR2(20) NULL ,
Квартира CHAR(18) NULL ,
ИНН VARCHAR2(20) NULL
);
CREATE UNIQUE INDEX XPKЗаявитель ON Заявитель
(ИД_Заявителя ASC);
ALTER TABLE Заявитель
ADD CONSTRAINT XPKЗаявитель
PRIMARY KEY (ИД_Заявителя);
CREATE TABLE Заявление
(
Номер_заявления_в_системе INTEGER
NOT NULL ,
Исполнитель
CHAR(18) NOT NULL ,
Статус VARCHAR2(20) NULL ,
ИД_Заявителя INTEGER NOT NULL ,
Адрес_участка CHAR(18) NOT NULL ,
Тип_собственности INTEGER NOT NULL ,
Площадь INTEGER NULL
);
CREATE UNIQUE INDEX XPKЗаявление ON Заявление
(Номер_заявления_в_системе ASC);
ALTER TABLE Заявление
ADD CONSTRAINT XPKЗаявление
PRIMARY KEY (Номер_заявления_в_системе);
CREATE TABLE Населенный_пункт
(
Код_КЛАДР CHAR(18) NOT NULL ,
Наименование VARCHAR2(20) NULL
);
CREATE UNIQUE INDEX XPKНаселенный_пункт ON Населенный_пункт
(Код_КЛАДР ASC);
ALTER TABLE Населенный_пункт
ADD CONSTRAINT XPKНаселенный_пункт
PRIMARY KEY (Код_КЛАДР);
CREATE TABLE Район
(
Код_КЛАДР CHAR(18) NOT NULL ,
Наименование VARCHAR2(20) NULL
);
CREATE UNIQUE INDEX XPKРайон ON Район
(Код_КЛАДР ASC);
ALTER TABLE Район
ADD CONSTRAINT XPKРайон PRIMARY KEY (Код_КЛАДР);
CREATE TABLE Сотрудник
(
Логин CHAR(18) NOT NULL ,
Фамилия VARCHAR2(20) NULL ,
Имя VARCHAR2(20) NULL ,
Отчество VARCHAR2(20) NULL
);
CREATE UNIQUE INDEX XPKСотрудник ON Сотрудник
(Логин ASC);
ALTER TABLE Сотрудник
ADD CONSTRAINT XPKСотрудник PRIMARY KEY (Логин);
CREATE TABLE Тип_собственности
(
Код_типа_по_справочнику INTEGER
NOT NULL ,
Наименование_типа_собственност
VARCHAR2(20) NULL
);
CREATE UNIQUE INDEX XPKТип_собственности ON
Тип_собственности
(Код_типа_по_справочнику ASC);
ALTER TABLE Тип_собственности
ADD CONSTRAINT XPKТип_собственности
PRIMARY KEY (Код_типа_по_справочнику);
CREATE TABLE Улица
(
Код_КЛАДР CHAR(18) NOT NULL ,
Наименование VARCHAR2(20) NULL
);
CREATE UNIQUE INDEX XPKУлица ON Улица
(Код_КЛАДР ASC);
ALTER TABLE Улица
ADD CONSTRAINT XPKУлица PRIMARY KEY (Код_КЛАДР);
ALTER TABLE Адрес_участка
ADD (CONSTRAINT R_11 FOREIGN KEY (Улица) REFERENCES
Улица(Код_КЛАДР));
ALTER TABLE Адрес_участка
ADD (CONSTRAINT R_13 FOREIGN KEY (Район) REFERENCES
Район(Код_КЛАДР));
ALTER TABLE Адрес_участка
ADD (CONSTRAINT R_14 FOREIGN KEY (Населенный_пункт)
REFERENCES Населенный_пункт(Код_КЛАДР));
ALTER TABLE Запрос_в_росреестр
ADD (CONSTRAINT R_3 FOREIGN KEY (Заявление_запроса)
REFERENCES Заявление(Номер_заявления_в_системе));
ALTER TABLE Заявитель
ADD (CONSTRAINT R_4 FOREIGN KEY (Документ_заявителя)
REFERENCES Документ(ИД_документа));
ALTER TABLE Заявитель
ADD (CONSTRAINT R_15 FOREIGN KEY (Улица) REFERENCES Улица(Код_КЛАДР));
ALTER TABLE Заявитель
ADD (CONSTRAINT R_16 FOREIGN KEY (Район) REFERENCES Район(Код_КЛАДР));
ALTER TABLE Заявитель
ADD (CONSTRAINT R_17 FOREIGN KEY (Населенный_пункт)
REFERENCES Населенный_пункт(Код_КЛАДР));
ALTER TABLE Заявление
ADD (CONSTRAINT R_2 FOREIGN KEY (ИД_Заявителя) REFERENCES
Заявитель(ИД_Заявителя));
ALTER TABLE Заявление
ADD (CONSTRAINT R_5 FOREIGN KEY (Тип_собственности)
REFERENCES Тип_собственности(Код_типа_по_справочнику));
ALTER TABLE Заявление
ADD (CONSTRAINT R_7 FOREIGN KEY (Адрес_участка)
REFERENCES Адрес_участка(Кадастровый_номер));
ALTER TABLE Заявление
ADD (CONSTRAINT R_10 FOREIGN KEY (Исполнитель)
REFERENCES Сотрудник(Логин));
CREATE TRIGGER tI_Адрес_участка BEFORE INSERT
ON Адрес_участка for each row
-- ERwin Builtin 8 сентября 2013 г. 18:02:39
-- INSERT trigger on Адрес_участка
DECLARE NUMROWS INTEGER;
BEGIN
/* ERwin Builtin 8 сентября 2013 г. 18:02:39
*/
/* Улица R/11 Адрес_участка
on child insert restrict */
/* ERWIN_RELATION:CHECKSUM="00033632",
PARENT_OWNER="", PARENT_TABLE="Улица"
CHILD_OWNER="", CHILD_TABLE="Адрес_участка"
P2C_VERB_PHRASE="R/11", C2P_VERB_PHRASE="",
FK_CONSTRAINT="R_11", FK_COLUMNS="Улица"
*/
SELECT count(*) INTO NUMROWS
FROM Улица
WHERE
/* %JoinFKPK(:%New,Улица,"
= "," AND") */
:new.Улица
= Улица.Код_КЛАДР;
IF (
/* %NotnullFK(:%New," IS NOT NULL
AND") */
NUMROWS = 0
)
THEN
raise_application_error(
-20002,
'Cannot insert Адрес_участка
because Улица does not exist.'
);
END IF;
/* ERWIN_RELATION:CHECKSUM="00000000",
PARENT_OWNER="", PARENT_TABLE="Район"
CHILD_OWNER="", CHILD_TABLE="Адрес_участка"
P2C_VERB_PHRASE="R/13", C2P_VERB_PHRASE="",
FK_CONSTRAINT="R_13", FK_COLUMNS="Район"
*/
SELECT count(*) INTO NUMROWS
FROM Район
WHERE
/* %JoinFKPK(:%New,Район,"
= "," AND") */
:new.Район
= Район.Код_КЛАДР;
IF (
/* %NotnullFK(:%New," IS
NOT NULL AND") */
NUMROWS = 0
)
THEN
raise_application_error(
-20002,
'Cannot insert Адрес_участка
because Район does not exist.'
);
END IF;
/* ERWIN_RELATION:CHECKSUM="00000000",
PARENT_OWNER="", PARENT_TABLE="Населенный_пункт"
CHILD_OWNER="", CHILD_TABLE="Адрес_участка"
P2C_VERB_PHRASE="R/14", C2P_VERB_PHRASE="",
FK_CONSTRAINT="R_14", FK_COLUMNS="Населенный_пункт"
*/
SELECT count(*) INTO NUMROWS
FROM Населенный_пункт
WHERE
/* %JoinFKPK(:%New,Населенный_пункт,"
= "," AND") */
:new.Населенный_пункт
= Населенный_пункт.Код_КЛАДР;
IF (
/* %NotnullFK(:%New," IS NOT NULL
AND") */
NUMROWS = 0
)
THEN
raise_application_error(
-20002,
'Cannot insert Адрес_участка
because Населенный_пункт does not exist.'
);
END IF;
END;
CREATE TRIGGER tD_Адрес_участка AFTER DELETE
ON Адрес_участка for each row
-- ERwin Builtin 8 сентября 2013 г. 18:02:39
-- DELETE trigger on Адрес_участка
DECLARE NUMROWS INTEGER;
BEGIN
/* ERWIN_RELATION:CHECKSUM="0000eae5",
PARENT_OWNER="", PARENT_TABLE="Адрес_участка"
CHILD_OWNER="", CHILD_TABLE="Заявление"
P2C_VERB_PHRASE="R/7", C2P_VERB_PHRASE="",
FK_CONSTRAINT="R_7", FK_COLUMNS="Адрес_участка"
*/
SELECT count(*) INTO NUMROWS
FROM Заявление
WHERE
/* %JoinFKPK(Заявление,:%Old,"
= "," AND") */
Заявление.Адрес_участка
= :old.Кадастровый_номер;
IF (NUMROWS > 0)
THEN
raise_application_error(
-20001,
'Cannot delete Адрес_участка
because Заявление exists.'
);
END IF;
END;
CREATE TRIGGER tU_Адрес_участка AFTER UPDATE
ON Адрес_участка for each row
-- ERwin Builtin 8 сентября 2013 г. 18:02:39
-- UPDATE trigger on Адрес_участка
DECLARE NUMROWS INTEGER;
BEGIN
/* ERwin Builtin 8 сентября 2013 г. 18:02:39 */
/* Адрес_участка R/7 Заявление
on parent update restrict */
/* ERWIN_RELATION:CHECKSUM="00047bff", PARENT_OWNER="",
PARENT_TABLE="Адрес_участка"
CHILD_OWNER="", CHILD_TABLE="Заявление"
P2C_VERB_PHRASE="R/7", C2P_VERB_PHRASE="",
FK_CONSTRAINT="R_7", FK_COLUMNS="Адрес_участка"
*/
IF
/* %JoinPKPK(:%Old,:%New," <> ","
OR ") */
Адрес_участка.Кадастровый_номер
<> Адрес_участка.Кадастровый_номер
THEN
SELECT count(*) INTO NUMROWS
FROM Заявление
WHERE
/* %JoinFKPK(Заявление,:%Old,"
= "," AND") */
Заявление.Адрес_участка
= :old.Кадастровый_номер;
IF (NUMROWS > 0)
THEN
raise_application_error(
-20005,
'Cannot update Адрес_участка
because Заявление exists.'
);
END IF;
END IF;
ERWIN_RELATION:CHECKSUM="00000000", PARENT_OWNER="",
PARENT_TABLE="Улица"
CHILD_OWNER="", CHILD_TABLE="Адрес_участка"
P2C_VERB_PHRASE="R/11", C2P_VERB_PHRASE="",
FK_CONSTRAINT="R_11", FK_COLUMNS="Улица"
*/
SELECT count(*) INTO NUMROWS
FROM Улица
WHERE
/* %JoinFKPK(:%New,Улица,"
= "," AND") */