Опубликован: 25.11.2008 | Доступ: свободный | Студентов: 4433 / 677 | Оценка: 4.46 / 4.18 | Длительность: 26:08:00
Лекция 8:

Принципы поддержки целостности в реляционной модели данных

< Лекция 7 || Лекция 8: 1234 || Лекция 9 >

Средства определения схемы базы данных

В стандарте SQL1 задается спецификация оператора описания схемы базы данных, но не указывается способ создания собственно базы данных, поэтому в различных СУБД используются неодинаковые подходы к этому вопросу.

Например, в СУБД ORACLE база данных создается в ходе установки программного обеспечения собственно СУБД. Все таблицы пользователей помещаются в единую базу данных. Однако они могут быть разделены на группы, объединенные в подсхемы. Понятие подсхемы не стандартизировано в SQL и не используется в других СУБД.

В состав СУБД INGRES входит специальная системная утилита, имеющая имя CREATEDB, которая позволяет создавать новые базы данных. Права на использование этой утилиты имеет администратор сервера. Для удаления базы данных существует соответствующая утилита DESTROYDB.

В СУБД MS SQL Server существует специальный оператор CREATE DATABASE, который является частью языка определения данных, для удаления базы данных в языке определен оператор DROP DATABASE. Правами на создание баз данных наделяются администраторы баз данных, которых в общем случае может быть несколько. Правами более высокого уровня обладает администратор сервера баз данных (SQL Server), который и может предоставить права администратора базы данных другим пользователям сервера. Администраторы баз данных могут удалить только свою базу данных. Приведем пример оператора создания схемы базы данных в MS SQL Server 7.0:

CREATE DATABASE database_name
[ON [PRIMARY][<спецификация файла>[,...n]][,<группа файлов> [,...n]]]
   [ LOG ON { спецификация файла> [,...n]} ][ FOR LOAD | FOR ATTACH ] 
<спецификация файла> ::= 
( [ NAME = логическое имя файла,]FILENAME = 'физическое имя файла'
  [, SIZE = размер][, MAXSIZE = { максимальный размер | UNLIMITED } ]
  [, FILEGROWTH = инкремент увеличения файла] ) [,...n] 
<группа файлов>::= FILEGROUP имя группы файлов спецификация файла> [,...n]

Здесь

  • database_name — имя базы данных, идентификатор в системе;
  • ON — ключевое слово, которое означает, что далее будут заданы спецификации файлов, которые будут использованы для размещения базы данных;
  • PRIMARY — ключевое слово, которое определяет первичное файловое пространство, в котором будет размещена собственно база данных;
  • LOG ON — ключевое слово, которое задает спецификацию файлов, которые будут использованы для хранения журналов транзакций;
  • FOR LOAD — ключевое слово, которое определяет, что после создания базы данных будет произведена загрузка базы данных данными;
  • FOR ATTACH — предложение, которое определяет, что база данных для управления будет подсоединена к другому серверу.

Почти все параметры, кроме имени базы данных, являются необязательными, поэтому оператор создания простой базы данных "Библиотека" может выглядеть следующим образом:

CREATE DATABASE Library

Для изменения схемы базы данных в MS SQL Server 7.0 может быть использована команда:

ALTER DATABASE database
{ ADD FILE спецификация файлов> [,...n] [TO FILEGROUP filegroup_name]
| ADD LOG FILE спецификация файлов> [,...n]
| REMOVE FILE имя_файла
| ADD FILEGROUP имя группы файлов REMOVE FILEGROUP имя группы_файлов
| MODIFY FILE спецификация файлов>
| MODIFY FILEGROUP имя_группы_файлов имя_свойства_группы файлов}

Здесь свойства группы файлов определяет одно из допустимых ключевых слов:

  • READONLY — только для чтения;
  • READWRITE — для чтения и записи;
  • DEFAULT — назначает данную группу файлов в качестве группы по умолчанию, в которой размещаются данные, если не задано дополнительных условий размещения информации.

Как видно, при изменении схемы базы данных в нее могут быть добавлены ( ADD ) дополнительные файлы и файловые группы или удалены ( REMOVE ) ранее определенные файлы или файловые группы. Назначение этих файлов нам будет более понятно после того, как мы познакомимся с физическими моделями и файловыми структурами, используемыми для хранения данных в базах данных.

Сейчас мы познакомимся с последней командой, которая предназначена для удаления базы данных. В MS SQL Server 7.0 это команда имеет следующий синтаксис:

DROP DATABASE database_name

После выполнения этой команды уничтожается вся база данных вместе с содержащимися в ней данными.

Средства изменения описания таблиц и средства удаления таблиц

В язык SQL добавлены средства изменения схемы таблиц. Что можно и что нельзя изменять в описании таблицы? В стандарте SQL2 добавлены достаточно широкие возможности по модификации уже существующих схем таблиц. Для модификации таблиц используется оператор ALTER TABLE, который позволяет выполнить следующие операции изменения для схемы таблицы:

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

Синтаксис оператора ALTER TABLE:

<Изменить описание таблицы>::= ALTER TABLE <имя таблицы> 
   { ADD определение столбца>
     ALTER <имя столбца> {SET DEFAULT <значение> 
     DROP DEFAULT } |
     DROP <имя столбца> {CASCADE | RESTRICT} | 
     ADD { <определение первичного ключа>| 
     <определение внешнего ключа> | 
     <условие уникальности данных> | 
     <условие проверки>  } | 
     DROP CONSTRAINT имя условия { CASCADE | 
     RESTRICT} }

Одним оператором ALTER TABLE можно провести только одно из перечисленных изменений, например, за один раз можно добавить один столбец. Если вам требуется добавить два столбца, то необходимо применить два оператора.

Давайте рассмотрим несколько примеров. Чаще всего применяется операция добавления столбца. Предложение определения нового столбца в операторе ALTER TABLE имеет точно такой же синтаксис, как и в операторе создания таблицы. Добавим столбец EDUCATION (образование), содержащий символьный тип данных, с заданным перечнем значений ("начальное", "среднее", "неоконченное высшее", "высшее").

ALTER TABLE READERS
ADD EDUCATION varchar (30) DEFAULT NULL
CHECK (EDUCATION IS NULL OR
  EDUCATION= "начальное" OR
  EDUCATION= "среднее " OR EDUCATION= "неоконченное высшее" OR
  EDUCATION= "высшее" )

В таблицу READERS будет добавлен столбец EDUCATION, в который по умолчанию будут добавлены все кортежи неопределенного значения. В дальнейшем эти значения могут быть заменены на одно из допустимых символьных значений.

Добавим ограничение на соответствие между датами взятия и возврата книги в таблице EXEMPLAR. Действительно, если даты введены, то требуется, чтобы дата возврата книги была бы больше на срок выдачи книги. Считаем, что стандартным сроком являются 2 недели. Теперь сформулируем оператор изменения таблицы EXEMPLARE:

ALTER TABLE EXEMPLARE
ADD CONSTRAINT CK_ EXEMPLARE CHECK ((DATA_IN IS NULL AND DATA_OUT IS NULL) OR 
   (DATA_OUT >= DATA_IN +14) )

Здесь мы применили операцию сложения к календарной дате, которая предполагает, что добавляют заданное число дней.

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

При изменении первичного ключа таблицы следует быть внимательными. Во-первых, у исходной таблицы могут быть подчиненные, при этом первичный ключ исходной таблицы является внешним ключом для подчиненных таблиц, и просто его удалить невозможно, СУБД контролирует ссылочную целостность и не позволит выполнить операцию удаления первичного ключа таблицы, если на него имеются ссылки. Следовательно, в этом случае порядок изменения первичного ключа должен быть таким, как на рис. 8.1:

Алгоритм изменения первичного ключа таблицы

Рис. 8.1. Алгоритм изменения первичного ключа таблицы

Чаще всего операция ALTER TABLE применяется в CASE-системах при автоматической генерации скриптов создания таблиц в базе данных. В этих системах универсальный алгоритм предполагает сначала создание всех таблиц, которые заданы в даталогической модели, и только после этого добавляются соответствующие связи. И это понятно — в отличие от человеческого разума искусcтвенный интеллект CASE-системы будет испытывать затруднения в определении иерархических взаимосвязей таблиц базы данных, поэтому он предпочитает использовать универсальный алгоритм, в котором сначала все объекты определяются, а затем добавляются соответствующие свойства для атрибутов, которые являются внешними ключами с указанием требуемых ссылок. В этом случае все операции назначения внешних ключей будут считаться корректными, потому что все объекты были описаны заранее, и для такого алгоритма порядок создания таблиц безразличен. Далее приведен скрипт, который был получен при разработке схемы базы данных "Библиотека" в PowerDesigner6.1. По умолчанию для каждой таблицы создается индекс по первичному ключу, так что кроме знакомых операций создания и изменения таблиц мы увидим еще и операцию создания индексов ( CREATE INDEX ), после изучения физических моделей в базах данных мы еще вернемся к этой операции, а пока примем ее на веру. При создании даталогичекой модели в качестве СУБД был выбран сервер MS SQL Server 6.X, и для этого сервера скрипт был сгенерирован на встроенном языке этой СУБД, называмом TransactSQL. В нем операция USE <имя базы данных> соответствует операции открытия базы данных, а команда go означает переход к выполнению следующей команды.

/* ============================================================ */
/* Database name: LIBRARY                                       */
/* DBMS name:  Microsoft SQL Server 6.x                         */
/* Created on: 06.10.00 18:56                                   */
/* ============================================================ */
/* ============================================================ */
/* Database name: LIBRARY                                       */
/* ============================================================ */
use LIBRARY
go
/* ============================================================ */
/* Table: BOOKS                                                 */
/* ============================================================ */
create table BOOKS 
(
  ISBN          varchar(14)   not null,
  TITLE         varchar(255)  not null,
  AUTOR         varchar(30)   null,
  COAUTOR       varchar(30)   null,
  PUBLICHER     varchar(30)   null,
  WHERE_PUBLICH varchar(30)   null,
  YEAR_IZD      smallint     not null
  constraint CKC_YEAR_IZD_BOOKS check (
  YEAR_PUBL >= 1969 AND YEAR_PUBL <= YEAR(GetDate())),
  PAGES smallint not null
  constraint CKC_PAGES_BOOKS check (
  PAGES between 5 and 1000),
  constraint PK_BOOKS primary key (ISBN),
  constraint CKT_BOOKS check (
  (AUTOR IS NOT NULL OR (AUTOR IS NULL AND COAUTOR IS NULL))) 
) 
go 
/* ============================================================ */
/* Table: READERS                                               */
/* ============================================================ */
create table READERS 
(
  NUM_READER   int not null,
  NAME        varchar(30)   not null,
  BIRTH_DAY    datetime     not null
  constraint CKC_BIRTH_DAY_READERS check (
  (DateDiff(year, GetDate(),BIRTH_DAY) >=17 )),
  SEX        char(1)     not null
  constraint CKC_SEX_READERS check (
  SEX in ('М','Ж','м','ж')),
  HOME_PHON    char(9)     null,
  WORK_PHON    char(9)     null,
  constraint PK_READERS primary key (NUM_READER),
  constraint CKT_READERS check (
  (HOME_PHON IS NOT NULL OR WORK_PHON IS NOT NULL)) 
) 
go 
/* ============================================================ */
/* Table: CATALOG                                               */
/* ============================================================ */
create table CATALOG 
(
  KW_KOD    smallint     not null,
  NAME_KW   varchar(255)  null,
  constraint PK_CATALOG primary key (KW_KOD) 
) 
go 
/* ============================================================ */
/* Table: EXEMPLAR                                              */
/* ============================================================ */
create table EXEMPLAR 
(
  INV_NUMER  int         not null,
  ISBN       varchar(14) not null,
  NUM_READER int         null,
  PRESENT    bitnot      null,
  DATE_IN    datetime    null,
  DATE_OUT   datetime    null,
  constraint PK_EXEMPLAR primary key (INV_NUMER) 
) 
go 
/* ============================================================ */
/* Index: RELATION_43_FK                                        */
/* ============================================================ */
create index RELATION_43_FK on EXEMPLAR (ISBN)
go
/* ============================================================ */
/* Index: RELATION_44_FK                                        */
/* ============================================================ */
create index RELATION_44_FK on EXEMPLAR (NUM_READER)
go
/* ============================================================ */
/* Table: RELATION_67                                           */
/* ============================================================ */
create table RELATION_67 
(
  ISBN     varchar(14)   not null,
  KW_KOD   smallint      not null,
constraint PK_RELATION_67 primary key (ISBN, KW_KOD) ) go
/* ============================================================ */
/* Index: IOIINEONY_E_IAEANOE_CIAIEE_FK                         */
/* ============================================================ */
create index IOIINEONY_E_IAEANOE_CIAIEE_FK on RELATION_67 (ISBN)
go
/* ============================================================ */
/* Index: I_AANOAAEAIA_A_EIEAAO_FK                              */
/* ============================================================ */
create index I_AANOAAEAIA_A_EIEAAO_FK on RELATION_67 (KW_KOD)
go
alter table EXEMPLAR
  add constraint FK_EXEMPLAR_RELATION__BOOKS foreign key (ISBN)
  references BOOKS (ISBN) 
go 
alter table EXEMPLAR
  add constraint FK_EXEMPLAR_RELATION__READERS foreign key (NUM_READER)
  references READERS (NUM_READER) 
go 
alter table RELATION_67
  add constraint FK_RELATION_IOIINEONY_BOOKS foreign key (ISBN)
  references BOOKS (ISBN) 
go 
alter table RELATION_67
  add constraint FK_RELATION_I_AANOAAE_CATALOG foreign key (KW_KOD)
  references CATALOG (KW_KOD) 
go

В языке SQL присутствует и операция удаления таблиц. Синтаксис этой операции предельно прост:

<Удалить таблицу>::= DROP TABLE <имя таблицы> [CASCADE | RESTRICT]

Параметр CASCADE означает, что при удалении таблицы одновременно удаляются и все объекты, связанные с ней. С таблицей, кроме рассмотренных ранее ограничений, могут быть связаны также объекты типа триггеров и представления. Понятие представления будет рассмотрено в следующем подразделе, а триггеров мы коснемся в разделах, связанных с архитектурой клиент-сервер. Однако операция удаления объектов определяется еще правами пользователей, что связано с концепцией безопасности в базах данных. Это значит, что если вы не являетесь владельцем объекта, то вы можете не иметь прав на его удаление. И в этом случае синтаксически правильный оператор DROP TABLE не может быть выполнен системой в силу отсутствия прав на удаление связанных с удаляемой таблицей объектов. Кроме того, операция удаления таблицы не должна нарушать целостность базы данных, поэтому удалять таблицу, на которую имеются ссылки других таблиц, невозможно.

Например, в нашей схеме, связанной с библиотекой, мы не можем удалить ни таблицу BOOKS, ни таблицу READERS, ни таблицу CATALOG. У этих таблиц есть связь с подчиненными таблицами EXEMPLAR и RELATION_67. Поэтому если вы хотите удалить некоторый набор таблиц, то сначала необходимо грамотно построить последовательность их удаления, которая не нарушит базовых принципов поддержки целостности вашей схемы БД. В нашем примере последовательность операторов удаления таблиц может быть следующей:

DROP TABLE EXEMPLAR 
DROP TABLE RELATION_67 
DROP TABLE CATALOG 
DROP TABLE READERS 
DROP TABLE BOOKS
< Лекция 7 || Лекция 8: 1234 || Лекция 9 >
Михаил Дубовик
Михаил Дубовик

В лекции как пример отношения в третьей нормальной форме приводится такая схема: (Номер зач. кн.\ ФИО \ Специальность \ Группа). Первичный ключ - Номер зач. кн. Но ведь существует следующая транзитивная зависимость: 

Номер зач. кн. -> Группа -> Специальность.

Получается, что отношение все же еще во второй нормальной форме. Или в моих рассуждениях ошибка?

Михаил Скок
Михаил Скок
Валентин Федченко
Валентин Федченко
Россия
Атанас Маринов
Атанас Маринов
Болгария