3. Лекция: Разработка модели базы данных

Рассмотрены основные этапы проектирования информационной системы и ее базы данных: текстового описания задачи, построение концептуальной и физической модели БД в системе CASE Studio, генерация программного кода на основе физической модели для двух различных СУБД. Цель: освоение главных принципов проектирования баз данных.

Использование методологии IDEF1X для разработки концептуальной модели данных

Важнейшая цель проектирования информационной модели - выработка непротиворечивой структурированной интерпретации реально существующей информации изучаемой предметной области и взаимодействия между ее структурными компонентами

Понятие концептуальной модели данных связано с методологией семантического моделирования данных, т.е. с представлением данных в контексте их взаимосвязей с другими данными.

Методология IDEF1X - один из подходов к семантическому моделированию данных, основанный на концепции "сущность-связь" (Entity-Relationship). Это инструмент для анализа информационной структуры систем различной природы. Информационная модель, построенная с помощью IDEF1X-методологии, отображает логическую структуру информации об объектах системы

Таким образом, концептуальная модель, представленная в соответствии со стандартом IDEF1X, является логической схемой базы данных для проектируемой системы

Основными объектами концептуальной модели являются сущности и связи.

Сущность - некоторый обособленный объект или событие моделируемой системы, имеющий определенный набор свойств - атрибутов. Отдельный элемент этого множества называется "экземпляром сущности". Сущность может обладать одним или несколькими атрибутами, которые однозначно идентифицируют каждый образец сущности, и может обладать любым количеством связей с другими сущностями.

Правила для атрибутов сущности:

  1. Каждый атрибут должен иметь уникальное имя.
  2. Сущность может обладать любым количеством атрибутов.
  3. Сущность может обладать любым количеством наследуемых атрибутов, но наследуемый атрибут должен быть частью первичного ключа сущности-родителя.
  4. Для каждого экземпляра сущности должно существовать значение каждого его атрибута (правило необращения в нуль - Not Null).
  5. Ни один из экземпляров сущности не может обладать более чем одним значением для ее атрибута.

Сущность изображается на ER-диаграмме в виде прямоугольника, в верхней части которого приводится ее название; далее следует список атрибутов. Ключевые атрибуты могут быть выделены подчеркиванием или иным способом.

Стандарт IDEF1X описывает способы изображения двух типов сущностей - независимой и зависимой, и связей - идентифицирующих и неидентифицирующих (см. рис. 3.1).


увеличить изображение
Рис. 3.1.  Изображение сущностей и связей по стандарту IDEF1X

Каждая сущность может обладать любым количеством связей с другими сущностями.

Сущность является независимой, если каждый ее экземпляр может быть однозначно идентифицирован без определения его связей с другими сущностями.

Сущность называется зависимой, если однозначная идентификация ее экземпляра зависит от его связей с другими сущностями.

Сущность может обладать атрибутами, которые наследуются через связь с родительской сущностью. Последние обычно являются внешними ключами (FK на рис. 3.1) и служат для организации связей между сущностями. Если внешний ключ сущности используется в качестве ее первичного ключа (PK) или как часть составного первичного ключа, то сущность является зависимой от родительской сущности. Если внешний ключ не является первичным и не входит в составной первичный ключ, то сущность является независимой от родительской сущности.

Если сущность является зависимой, то связь ее с родительской сущностью называется идентифицирующей, в противном случае - неидентифицирующей.

Связь изображается на ER-диаграмме линией, проводимой между сущностью-родителем и сущностью-потомком с точкой на конце линии у сущности-потомка. идентифицирующая связь изображается сплошной линией, неидентифицирующая - пунктирной.

Связи дается имя, выражаемое грамматической формой глагола. Для связи дополнительно может присутствовать указание мощности: какое количество экземпляров сущности-потомка может существовать для сущности-родителя. Имя связи всегда формируется с точки зрения родителя, так что может быть образовано предложение, если соединить имя сущности родителя, имя связи, выражение мощности и имя сущности-потомка (например "много СТУДЕНТов - сдают - ЭКЗАМЕН").

Принципы изображения концептуальных моделей баз данных стандарта IDEF1 и IDEF1X используют CASE Studio и другие CASE-средства. Подобные системы позволяют на основе концептуальной модели генерировать физическую модель и программный код создания базы данных для большинства наиболее распространенных СУБД и серверов баз данных.

В рассматриваемом далее примере концептуальной модели (см. рис. рис. 3.5) все сущности - независимые и связи между ними - неидентифицирующие, хотя возможны и другие варианты ключей и связей.

Описание модели данных информационной системы "Контингент студентов университета"

Первоначальный этап - создание текстового описания моделируемой системы.

Постановка задачи. Главная задача системы - сохранение в базе данных всех необходимых сведений о студентах и их успеваемости, формирование необходимых печатных форм для проведения зачетной и экзаменационной работы преподавателей, генерация сводных итогов по результатам сессии для руководящих работников деканатов, институтов и университета. При разработке системы следует учитывать, что она взаимодействует с системами "Абитуриент", "Стипендия" и "Кадры университета". Информация о студентах первоначально поступает из системы "Абитуриент" и редактируется на уровне деканатов. Она должна также удовлетворять требованиям бухгалтерского учета по начислению стипендий. Система должна использовать справочник специальностей, утвержденный в вышестоящем министерстве. Информация об успеваемости студентов накапливается постоянно и сохраняется за весь период обучения, после чего переносится в архивное хранилище данных. В системе должен использоваться единый справочник дисциплин (предметов) для всех подразделений университета.

Концептуальная модель базы данных

На концептуальном уровне данные информационной системы состоят из двух основных сущностей: "Студент" и "Успеваемость".

Минимальный состав атрибутов и их описание для сущности "Студент" представлены в табл. 3.1.

Таблица 3.1. Атрибуты сущности "Студент"
Имя атрибута Описание, особенности использования
Номер зачетки Первичный ключ - уникальный номер, однозначно идентифицирующий студента университета
Фамилия, имя, отчество Является простым с точки зрения экземпляра сущности, при необходимости из общего поля можно выделить составляющие его фамилию, имя и отчество или фамилию и инициалы, однако на практике часто этот атрибут разделяют на 3 отдельных; первый вариант является более экономичным по необходимой общей ширине поля таблицы
Дата поступления в университет В нашей стране наиболее часто используется формат работы с датой в виде ДД.ММ.ГГ, что совпадает с немецким (German) форматом дат. Количество цифр года: либо две - для новых систем, поддерживающих заданный в Microsoft Windows годичный интервал (Панель управления - Язык и стандарты - Дата - "При вводе двух цифр года воспринимать их как год между:"), или для систем, в которых аналогичный интервал может быть задан в программе, - либо 4 цифры
Факультет (№ факультета) Может быть сложным (кроме кода и названия, может содержать и другие сведения); даже в том случае, если для сущности "Студент" мы хотим сохранять название факультета, оно должно быть представлено в одинаковом виде для каждого факультета, поэтому, в соответствии с принципами нормализации баз данных, этот атрибут следует представить в виде номера, являющегося внешним ключом для новой сущности - "Факультет", в которой каждому номеру, являющемуся первичным ключом, будут соответствовать название и прочие атрибуты этой сущности
Специальность(код специальности) Может быть сложным, кроме того, необходимо использовать справочник министерства с утвержденными кодами специальностей, поэтому данный атрибут должен хранить код специальности - внешний ключ для первичного ключа новой сущности "Специальность"
Курс Число от 1 до 5
Номер группы Трехзначное число
Номер паспорта Состав и вид паспортных данных определяется требованиями бухгалтерской отчетности перед налоговыми органами, фондами социального страхования и пенсионным фондом
... Прочие атрибуты, которых может быть достаточно много

В табл. 3.2-3.5 представлены атрибуты сущностей "Успеваемость", "Факультет", "Специальность", "Предмет".

Таблица 3.2. Атрибуты сущности "Успеваемость"
Имя атрибута Описание, особенности использования
Номер зачетки Внешний ключ (к сущности "Студент")
Номер семестра Число от 1 до 10
Предмет (№ предмета) Может быть сложным, его следует заменить на его номер (внешний ключ) и связать с новой сущностью "Предмет", состоящий, как минимум, из атрибутов "номер предмета" (первичный ключ) и "название предмета"
Оценка Может быть представлена цифрами от 0 до 5 или 1 буквой: например "н" - неявка
Дата получения оценки Формат даты обычно ДД.ММ.ГГ
Фамилия преподавателя Это поле может быть связано с сущностью "Преподаватель". В данном учебном примере ограничимся простым атрибутом
... Могут быть добавлены и другие атрибуты, например, номер экзаменационной ведомости
Таблица 3.3. Атрибуты сущности "Факультет"
Имя атрибута Описание, особенности использования
Номер факультета Первичный ключ
Название факультета Может быть достаточно длинным, но не более 255 символов
... Могут быть добавлены и другие атрибуты, например, декан, номер комнаты деканата и т.д.
Таблица 3.4. Атрибуты сущности "Специальность"
Имя атрибута Описание, особенности использования
Код специальности Первичный ключ - значение из справочника министерства
Название специальности Значение из справочника министерства
... Могут быть добавлены и другие атрибуты
Таблица 3.5. Атрибуты сущности "Предмет"
Имя атрибута Описание, особенности использования
№ предмета Первичный ключ
Название предмета Общий справочник университета
... Могут быть добавлены и другие атрибуты

В физической модели каждой сущности будет соответствовать таблица базы данных, а каждому атрибуту - поле таблицы. Имена таблиц и полей лучше задавать с использованием латинских букв и достаточно короткими для удобства использования при программировании и для совместимости с системами, не использующими кириллицу. Состав данных и связи в концептуальной и физической моделях показаны в табл. 3.6 и табл. 3.7.

Таблица 3.6. Состав базы данных информационной системы
№ п/п Сущности концептуальной модели Таблицы физической модели
Название Информация
1. "Студент" "SPISOK" "Список студентов"
2. "Успеваемость" "OCENKI" "Оценки студентов"
3. "Факультет" "FCLT" Справочник факультетов
4. "Специальность" "SPECT" Справочник специальностей
5. "Предмет" "PREDMET" Справочник предметов
Таблица 3.7. Связи между объектами базы данных информационной системы
№ п/п Концептуальная модель Физическая модель
1. "Студент" - "Успеваемость" "SPISOK" - "OCENKI"
2. "Студент" - "Факультет" "SPISOK" - "FCLT"
3. "Студент" - "Специальность" "SPISOK" - "SPECT"
4. "Успеваемость" - "Предмет" "OCENKI" - "PREDMET"

Использование системы CASE Studio для проектирования концептуальной и физической моделей базы данных

CASE Studio является профессиональным инструментом проектирования баз данных. Система предназначена для визуального создания и модификации диаграмм "сущность-связь" (ERD) и диаграмм потоков данных (DFD). Уровень представления ER-диаграмм может быть различен: от простейшего вида (имена сущностей и связи между ними) и до полной физической модели для выбранной СУБД. Сложные модели данных могут быть разбиты на отдельные логические фрагменты - субмодели.

Для разработанных диаграмм далее может быть сгенерирован программный код для создания таблиц, индексов, связей, хранимых процедур, пользователей и других компонентов различных СУБД (см. табл. 3.7.). Кроме того, предусмотрена возможность генерации ER-диаграмм для существующей базы данных (Reverse Engineering) с использованием для связи с БД прямого соединения, ODBC или ADO-драйверов.

При создании новой модели данных следует задать, для какой СУБД она проектируется, т.к. CASE Studio имеет возможность построения полной физической модели базы данных с использованием индивидуальных свойств каждой БД - типы и свойства атрибутов (стандартные БД и пользователя), возможности описания ключей (первичные и внешние), связей, условий соблюдения ссылочной целостности, пользователей и их групп (ролей); возможности написания хранимых процедур и пр. В последующем можно будет выполнить конверсию физической модели для другой СУБД (меню Model - Database Convertion) с сохранением в виде копии.

Создание новой модели может начинаться с задания только имен сущностей и связей между ними, как показано на рис. 3.2, который соответствует описанному выше примеру. Связи (неидентифицирующего типа) следует создавать в направлении от предполагаемого первичного ключа к внешнему. Для всех связей в модели заданы условия соблюдения ссылочной целостности: каскадные изменения при изменении и удалении данных в главной таблице и контроль с запретом неверного ввода (restrict) в операциях обновления и добавления данных в дочерних таблицах (см. рис. 3.3).


увеличить изображение
Рис. 3.2.  Простейший вид ER-диаграммы в системе CASE Studio

Далее для каждой сущности в окне свойств (рис. рис. 3.4) можно задать название соответствующей ей таблицы в физической модели, названия атрибутов концептуальной модели и полей физической модели с указанием их типа, размера, с заданием ключей, надписей (Notes), описаний и пр. Следует отметить, что для описания полей физической модели необходимо знать типы данных той СУБД, для которой она разрабатывается. В последующем будут разобраны типы данных полей в системах Visual FoxPro, Microsoft Access и Microsoft SQL Server.

Окно описания свойств связи
Рис. 3.3.  Окно описания свойств связи

Окно описания свойств сущности и таблицы
Рис. 3.4.  Окно описания свойств сущности и таблицы

После описания всех атрибутов и полей может быть использована различная детализация показа концептуальной (в меню View - Display Level, см. рис. 3.5) и физической (в меню View нужно поставить галочку у позиции Physical View) моделей.

Меню задания режима показа модели
Рис. 3.5.  Меню задания режима показа модели

На рис. 3.6 показана концептуальная модель для описанного выше примера, на рис. рис. 3.7 - физическая модель для СУБД Oracle 9i.


увеличить изображение
Рис. 3.6.  Концептуальная модель базы данных


увеличить изображение
Рис. 3.7.  Физическая модель базы данных

Далее можно описать права групп пользователей и права отдельных пользователей (меню системы пункт Model - Users Roles и Model - Users), если эту информацию нужно использовать при создании базы данных.

На основе описания физической модели был сгенерирован текст программ для создания базы данных в СУБД Oracle (в меню системы пункт Model - Script Generation) и, после конвертации модели, - для Microsoft Access.

Сгенерированная Case Studio SQL-программа создания таблиц базы данных для сервера Oracle

/*
Created	02.02.2006
Modified	03.02.2006
Project	Kontingent
Model		Students
Company	AGTU
Author		Groshev
Version	2006.1
Database	Oracle 9i 
*/
Create table "Student" (
   "Nz" Char(7) NOT NULL ,
   "Fio" Char(45),
   "date_p" Date,
   "n_fclt" Decimal(2,0) NOT NULL ,
   "n_spect" Char(9) NOT NULL ,
   "kurs" Decimal(1,0),
   "n_grup" Char(10),
   "n_pasp" Char(10)) 
/
Create table "Ocenki" (
   "semestr" Decimal(2,0),
   "n_predm" Decimal(2,0) NOT NULL ,
   "ball" Char(1),
   "data_b" Date,
   "Prepod" Char(45),
   "Nz" Char(7) NOT NULL ) 
/
Create table "Predmet" (
   "n_predm" Decimal(2,0) NOT NULL ,
   "name_p" Char(120)) 
/
Create table "FCLT" (
   "n_fclt" Decimal(2,0) NOT NULL ,
   "name_f" Char(120)) 
/
Create table "SPECT" (
   "n_spect" Char(9) NOT NULL ,
   "name_S" Char(120)) 
/
Alter table "Student" add primary key ("Nz") 
/
Alter table "Predmet" add primary key ("n_predm") 
/
Alter table "FCLT" add primary key ("n_fclt") 
/
Alter table "SPECT" add primary key ("n_spect")
/
Alter table "Ocenki" add  foreign key ("Nz") references "Student" ("Nz")  
        on delete cascade
/
Alter table "Ocenki" add  foreign key ("n_predm") references "Predmet" ("n_predm")  
        on delete cascade
/
Alter table "Student" add  foreign key ("n_fclt") references "FCLT" ("n_fclt")  
        on delete cascade
/
Alter table "Student" add  foreign key ("n_spect") references "SPECT" ("n_spect")  
        on delete cascade
/
-- Update trigger for Student
Create Trigger "tu_Student" after update   
of "Nz","n_fclt","n_spect"
on  "Student" 
referencing new as new_upd old as old_upd for each row
declare numrows integer;
begin
     -- cascade child Ocenki update when parent Student changed
     if (:old_upd."Nz" != :new_upd."Nz")  then
     	begin
     	update "Ocenki"
     	set 	"Nz" = :new_upd."Nz"
     	where 	"Ocenki"."Nz" = :old_upd."Nz" ;
     	end;
     end if;
     -- restrict parent SPECT when child Student updated
     if :new_upd."n_spect" !=  :old_upd."n_spect" then
     	begin
     	select count( * ) 
     	into numrows
     	from "SPECT"
     	where 	:new_upd."n_spect" = "SPECT"."n_spect";
     	if ( numrows = 0 ) then
     		begin
     		RAISE_APPLICATION_ERROR(-20002,'Parent does not exist. Cannot update child.');
     		end;
     	end if;
     	end;
     end if;
     -- restrict parent FCLT when child Student updated
     if :new_upd."n_fclt" !=  :old_upd."n_fclt" then
     	begin
     	select count( * ) 
     	into numrows
     	from "FCLT"
     	where 	:new_upd."n_fclt" = "FCLT"."n_fclt";
     	if ( numrows = 0 ) then
     		begin
     		RAISE_APPLICATION_ERROR(-20002,'Parent does not exist. Cannot update child.');
     		end;
     	end if;
     	end;
     end if;
     
end;
/
-- Update trigger for Ocenki
Create Trigger "tu_Ocenki" after update   
of "n_predm","Nz"
on  "Ocenki" 
referencing new as new_upd old as old_upd for each row
declare numrows integer;
begin
     -- restrict parent Predmet when child Ocenki updated
     if :new_upd."n_predm" !=  :old_upd."n_predm" then
     	begin
     	select count( * ) 
     	into numrows
     	from "Predmet"
     	where 	:new_upd."n_predm" = "Predmet"."n_predm";
     	if ( numrows = 0 ) then
     		begin
     		RAISE_APPLICATION_ERROR(-20002,'Parent does not exist. Cannot update child.');
     		end;
     	end if;
     	end;
     end if;
     -- restrict parent Student when child Ocenki updated
     if :new_upd."Nz" !=  :old_upd."Nz" then
     	begin
     	select count( * ) 
     	into numrows
     	from "Student"
     	where 	:new_upd."Nz" = "Student"."Nz";
     	if ( numrows = 0 ) then
     		begin
     		RAISE_APPLICATION_ERROR(-20002,'Parent does not exist. Cannot update child.');
     		end;
     	end if;
     	end;
     end if;
     
end;
/
-- Update trigger for Predmet
Create Trigger "tu_Predmet" after update   
of "n_predm"
on  "Predmet" 
referencing new as new_upd old as old_upd for each row
declare numrows integer;
begin
     -- cascade child Ocenki update when parent Predmet changed
     if (:old_upd."n_predm" != :new_upd."n_predm")  then
     	begin
     	update "Ocenki"
     	set 	"n_predm" = :new_upd."n_predm"
     	where 	"Ocenki"."n_predm" = :old_upd."n_predm" ;
     	end;
     end if;
end;
/
-- Update trigger for FCLT
Create Trigger "tu_FCLT" after update   
of "n_fclt"
on  "FCLT" 
referencing new as new_upd old as old_upd for each row
declare numrows integer;
begin
     -- cascade child Student update when parent FCLT changed
     if (:old_upd."n_fclt" != :new_upd."n_fclt")  then
     	begin
     	update "Student"
     	set 	"n_fclt" = :new_upd."n_fclt"
     	where 	"Student"."n_fclt" = :old_upd."n_fclt" ;
     	end;
     end if;
end;
/
-- Update trigger for SPECT
Create Trigger "tu_SPECT" after update   
of "n_spect"
on  "SPECT" 
referencing new as new_upd old as old_upd for each row
declare numrows integer;
begin
     -- cascade child Student update when parent SPECT changed
     if (:old_upd."n_spect" != :new_upd."n_spect")  then
     	begin
     	update "Student"
     	set 	"n_spect" = :new_upd."n_spect"
     	where 	"Student"."n_spect" = :old_upd."n_spect" ;
     	end;
     end if;
end;
/
-- Insert trigger for Student
Create Trigger "ti_Student" after insert
on "Student" 
referencing new as new_ins for each row
declare numrows integer;
begin
-- restrict child Student when parent SPECT insert
if (:new_ins."n_spect" is not null) then
 	begin
   select count( * ) 
   into numrows
   from "SPECT"
   where 	:new_ins."n_spect" = "SPECT"."n_spect";
   IF ( numrows = 0 ) then
      begin
      RAISE_APPLICATION_ERROR(-20004,'Parent does not exist. Cannot insert child.');
      end;
   end if;
   end;
end if;
-- restrict child Student when parent FCLT insert
if (:new_ins."n_fclt" is not null) then
 	begin
   select count( * ) 
   into numrows
   from "FCLT"
   where 	:new_ins."n_fclt" = "FCLT"."n_fclt";
   
   IF ( numrows = 0 ) then
      begin
      RAISE_APPLICATION_ERROR(-20004,'Parent does not exist. Cannot insert child.');
      end;
   end if;
   end;
end if;
end;
/
-- Insert trigger for Ocenki
Create Trigger "ti_Ocenki" after insert
on "Ocenki" 
referencing new as new_ins for each row
declare numrows integer;
begin
-- restrict child Ocenki when parent Predmet insert
if (:new_ins."n_predm" is not null) then
 	begin
   select count( * ) 
   into numrows
   from "Predmet"
   where 	:new_ins."n_predm" = "Predmet"."n_predm";
   IF ( numrows = 0 ) then
      begin
      RAISE_APPLICATION_ERROR(-20004,'Parent does not exist. Cannot insert child.');
      end;
   end if;
   end;
end if;
-- restrict child Ocenki when parent Student insert
if (:new_ins."Nz" is not null) then
 	begin
   select count( * ) 
   into numrows
   from "Student"
   where 	:new_ins."Nz" = "Student"."Nz";
   IF ( numrows = 0 ) then
      begin
      RAISE_APPLICATION_ERROR(-20004,'Parent does not exist. Cannot insert child.');
      end;
   end if;
   end;
end if;
end;
/
Create role "Stud_admin"
/
Create role "Dekan"
/
Grant "Stud_admin" to "Petrov_P_P"
/
Grant "Dekan" to "Иванов_И_И"
/
/* Roles permissions */
Grant select on "Student" to "Stud_admin"
/
Grant update on "Student" to "Stud_admin"
/
Grant delete on "Student" to "Stud_admin"
/
Grant insert on "Student" to "Stud_admin"
/
Grant references on "Student" to "Stud_admin"
/
Grant select on "Student" to "Dekan"
/
Grant update on "Student" to "Dekan"
/
Grant delete on "Student" to "Dekan"
/
Grant insert on "Student" to "Dekan"
/
Grant references on "Student" to "Dekan"
/
Grant select on "Ocenki" to "Stud_admin"
/
Grant update on "Ocenki" to "Stud_admin"
/
Grant delete on "Ocenki" to "Stud_admin"
/
Grant insert on "Ocenki" to "Stud_admin"
/
Grant references on "Ocenki" to "Stud_admin"
/
Grant select on "Ocenki" to "Dekan"
/
Grant update on "Ocenki" to "Dekan"
/
Grant delete on "Ocenki" to "Dekan"
/
Grant insert on "Ocenki" to "Dekan"
/
Grant references on "Ocenki" to "Dekan"
/
Grant select on "Predmet" to "Stud_admin"
/
Grant update on "Predmet" to "Stud_admin"
/
Grant delete on "Predmet" to "Stud_admin"
/
Grant insert on "Predmet" to "Stud_admin"
/
Grant references on "Predmet" to "Stud_admin"
/
Grant select on "FCLT" to "Stud_admin"
/
Grant update on "FCLT" to "Stud_admin"
/
Grant delete on "FCLT" to "Stud_admin"
/
Grant insert on "FCLT" to "Stud_admin"
/
Grant references on "FCLT" to "Stud_admin"
/
Grant select on "SPECT" to "Stud_admin"
/
Grant update on "SPECT" to "Stud_admin"
/
Grant delete on "SPECT" to "Stud_admin"
/
Grant insert on "SPECT" to "Stud_admin"
/
Grant references on "SPECT" to "Stud_admin"
/
/* Users permissions */

Сгенерированная Case Studio программа создания таблиц базы данных для СУБД Access

' Created		02.02.2006
' Modified		03.02.2006
' Project		Kontingent 
' Model		Students	
' Company		AGTU 
' Author		Groshev	
' Version		2006.1
' Database		Access 2000 
'=======================================================
'=== MS Access 2000 database creation method
'===
'=== 1. Create a new database in the MS Access 2000
'=== 2. Create a new module
'=== 3. Copy the CASE Studio 2 output SQL script into the new MS Access 2000 module
'=== 4. Select from main menu "Tools" item "References..." and check 
'===     the "Microsoft DAO 3.6 Object Library."
'=== 5. Place your mouse cursor somewhere in the main procedure Main()
'=== 6. Run the module code (Click the "Run Sub/UserForm" button or press F5)
'=======================================================
Public dbs As DAO.Database
Public tdf As DAO.TableDef
Public idx As DAO.Index
Public rel As DAO.Relation
Sub Main()
Set dbs = CurrentDb()
On Error GoTo ErrorHandler
   Call CreateTables
   Call CreatePrimaryKeys
   Call CreateIndexes
   Call CreateAlterKeys
   Call CreateRelations
   Call CreateQueries
   MsgBox "Script successfully processed.", vbInformation
   Exit Sub
ErrorHandler:
   Select Case Err.Number
      Case 3010
         MsgBox "Table " & tdf.Name & " allready exist!", vbInformation
         Err.Clear
      Case 3284
         MsgBox "Index " & idx.Name & " for table " & tdf.Name & " allready exist!", vbInformation
         Err.Clear
      Case Else
         MsgBox Err.Description, vbCritical
   End Select
End Sub
' Create tables
'===============
Sub CreateTables()
Call CreateTable1 'Student
Call CreateTable2 'Ocenki
Call CreateTable3 'Predmet
Call CreateTable4 'FCLT
Call CreateTable5 'SPECT
End Sub
'=== Create table Student ======
Sub CreateTable1()
Set tdf = dbs.CreateTableDef( "Student" )
Call AddFieldToTable("Nz", dbText, 7, 0, "", "", "", TRUE )
Call AddFieldToTable("Fio", dbText, 45, 0, "", "", "", FALSE )
Call AddFieldToTable("date_p", dbDate, 0, 0, "", "", "", FALSE )
Call AddFieldToTable("n_fclt", dbSingle, 0, 0, "", "", "", TRUE )
Call AddFieldToTable("n_spect", dbText, 9, 0, "", "", "", TRUE )
Call AddFieldToTable("kurs", dbSingle, 0, 0, "", "", "", FALSE )
Call AddFieldToTable("n_grup", dbText, 10, 0, "", "", "", FALSE )
Call AddFieldToTable("n_pasp", dbText, 10, 0, "", "", "", FALSE )
dbs.TableDefs.Append tdf
End Sub
'=== Create table Ocenki ======
Sub CreateTable2()
Set tdf = dbs.CreateTableDef( "Ocenki" )
Call AddFieldToTable("semestr", dbSingle, 0, 0, "", "", "", FALSE )
Call AddFieldToTable("n_predm", dbSingle, 0, 0, "", "", "", TRUE )
Call AddFieldToTable("ball", dbText, 1, 0, "", "", "", FALSE )
Call AddFieldToTable("data_b", dbDate, 0, 0, "", "", "", FALSE )
Call AddFieldToTable("Prepod", dbText, 45, 0, "", "", "", FALSE )
Call AddFieldToTable("Nz", dbText, 7, 0, "", "", "", TRUE )
dbs.TableDefs.Append tdf
End Sub
'=== Create table Predmet ======
Sub CreateTable3()
Set tdf = dbs.CreateTableDef( "Predmet" )
Call AddFieldToTable("n_predm", dbSingle, 0, 0, "", "", "", TRUE )
Call AddFieldToTable("name_p", dbText, 120, 0, "", "", "", FALSE )
dbs.TableDefs.Append tdf
End Sub
'=== Create table FCLT ======
Sub CreateTable4()
Set tdf = dbs.CreateTableDef( "FCLT" )
Call AddFieldToTable("n_fclt", dbSingle, 0, 0, "", "", "", TRUE )
Call AddFieldToTable("name_f", dbText, 120, 0, "", "", "", FALSE )
dbs.TableDefs.Append tdf
End Sub
'=== Create table SPECT ======
Sub CreateTable5()
Set tdf = dbs.CreateTableDef( "SPECT" )
Call AddFieldToTable("n_spect", dbText, 9, 0, "", "", "", TRUE )
Call AddFieldToTable("name_S", dbText, 120, 0, "", "", "", FALSE )
dbs.TableDefs.Append tdf
End Sub
' Create primary keys
'=====================
Sub CreatePrimaryKeys()
'=== Create primary key for table Student ======
Set tdf = dbs.TableDefs( "Student" )
Set idx = tdf.CreateIndex( "pk_Student" )
idx.Primary = True
idx.Unique  = True
idx.IgnoreNulls = False
Call AddFieldToIndex( "Nz", False )
tdf.Indexes.Append idx
'=== Create primary key for table Predmet ======
Set tdf = dbs.TableDefs( "Predmet" )
Set idx = tdf.CreateIndex( "pk_Predmet" )
idx.Primary = True
idx.Unique  = True
idx.IgnoreNulls = False
Call AddFieldToIndex( "n_predm", False )
tdf.Indexes.Append idx
'=== Create primary key for table FCLT ======
Set tdf = dbs.TableDefs( "FCLT" )
Set idx = tdf.CreateIndex( "pk_FCLT" )
idx.Primary = True
idx.Unique  = True
idx.IgnoreNulls = False
Call AddFieldToIndex( "n_fclt", False )
tdf.Indexes.Append idx
'=== Create primary key for table SPECT ======
Set tdf = dbs.TableDefs( "SPECT" )
Set idx = tdf.CreateIndex( "pk_SPECT" )
idx.Primary = True
idx.Unique  = True
idx.IgnoreNulls = False
Call AddFieldToIndex( "n_spect", False )
tdf.Indexes.Append idx
End Sub
' Create indexes
'================
Sub CreateIndexes()
End Sub
' Create alter keys (unique indexes in MS ACCESS)
'================================================
Sub CreateAlterKeys()
End Sub
' Create relations
'==================
Sub CreateRelations()
'=== Create relations between parent table Student and child table Ocenki ======
Set rel = dbs.CreateRelation("Student_Ocenki")
rel.Table			= "Student"
rel.ForeignTable	= "Ocenki"
rel.Attributes	= dbRelationUpdateCascade+dbRelationDeleteCascade
Call AddFieldToRelation("Nz", "Nz")
dbs.Relations.Append rel
'=== Create relations between parent table Predmet and child table Ocenki ======
Set rel = dbs.CreateRelation("Predmet_Ocenki")
rel.Table			= "Predmet"
rel.ForeignTable	= "Ocenki"
rel.Attributes	= dbRelationUpdateCascade+dbRelationDeleteCascade
Call AddFieldToRelation("n_predm", "n_predm")
dbs.Relations.Append rel
'=== Create relations between parent table FCLT and child table Student ======
Set rel = dbs.CreateRelation("FCLT_Student")
rel.Table			= "FCLT"
rel.ForeignTable	= "Student"
rel.Attributes	= dbRelationUpdateCascade+dbRelationDeleteCascade
Call AddFieldToRelation("n_fclt", "n_fclt")
dbs.Relations.Append rel
'=== Create relations between parent table SPECT and child table Student ======
Set rel = dbs.CreateRelation("SPECT_Student")
rel.Table			= "SPECT"
rel.ForeignTable	= "Student"
rel.Attributes	= dbRelationUpdateCascade+dbRelationDeleteCascade
Call AddFieldToRelation("n_spect", "n_spect")
dbs.Relations.Append rel
End Sub
' Create queries
'================
Sub CreateQueries()
Dim qdf As QueryDef
End Sub
' Add fields to table
'=====================
Sub AddFieldToTable(FieldName As String, DataType As String, SizeCol As Integer, 
                               Attributes As Long, DefaultValue As Variant, ValText As String, 
                               ValRule As String, NotN As Boolean)
Dim fld As DAO.Field
Set fld = tdf.CreateField( FieldName, DataType )
If SizeCol 		<> 0 Then fld.Size	   	= SizeCol
If Attributes	<> 0 Then fld.Attributes	= Attributes
fld.Required 			= NotN
fld.DefaultValue 		= DefaultValue
fld.ValidationRule 	= ValRule
fld.ValidationText 	= ValText
tdf.Fields.Append fld
End Sub
' Add properties to table
'=========================
Sub AddPropertyToTable( PropertyName As String, Value As Variant, DataType As String)
Dim prp As DAO.Property
Set prp = tdf.CreateProperty(PropertyName, DataType, Value)
tdf.Properties.Append prp
End Sub
' Add properties to field
'=========================
Sub AddPropertyToField(FieldName As String, PropertyName As String, Value As Variant, 
                                    DataType As String)
Dim prp As DAO.Property
Dim fld As DAO.Field
Set fld = tdf.Fields( FieldName )
Set prp = fld.CreateProperty(PropertyName, DataType, Value)
fld.Properties.Append prp
End Sub
' Add fields to index
'=====================
Sub AddFieldToIndex( FieldName As String, Descending As Boolean )
Dim fld As DAO.Field
Set fld = idx.CreateField( FieldName )
If Descending = True Then fld.Attributes = dbDescending
idx.Fields.Append fld
End Sub
' Add fields to relation
'========================
Sub AddFieldToRelation( PKField As String, FKField As String )
Dim fld As DAO.Field
Set fld = rel.CreateField( PKField )
fld.ForeignName = FKField
rel.Fields.Append fld
End Sub