При выборе первичного ключа предпочтение 
должно отдаваться наиболее простым ключам. 
Атрибуты первичного ключа не должны содержать 
нулевых значений. Значения ключевых атрибутов 
не должны меняться в течение всего времени 
существования экземпляра сущности. Кроме 
этого, каждая сущность должна иметь, по 
крайней мере, один потенциальный ключ. 
Некоторые сущности могут иметь более 
одного возможного ключа. При выборе одного 
из них первичным остальные становятся 
альтернативными ключами (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") */