10. Таблицы (TABLE)

Таблица — наиболее важный и сложный объект реляционной базы данных. В таблицах хранятся все обрабатываемые клиентскими программами данные базы данных. Все строки одной таблицы имеют одинаковую структуру. Количество строк в таблице произвольное. Таблица должна содержать хотя бы один столбец. Обрабатываемые (пользовательские) данные хранятся в таблицах, создаваемых пользователем при помощи оператора CREATE TABLE и изменяемых оператором ALTER TABLE. Системные данные (метаданные, описывающие объекты базы данных) хранятся в системных таблицах, которые создаются автоматически при первоначальном создании базы данных. База данных может содержать не более 32640 пользовательских таблиц.

10.1. Создание таблиц

Таблица создается оператором CREATE TABLE. Синтаксис оператора представлен в листинге .

Листинг 10.1 Синтаксис оператора создания таблицы CREATE TABLE

CREATE [GLOBAL TEMPORARY] TABLE <имя таблицы>
   [EXTERNAL [FILE] '<спецификация файла>' [ADAPTER 'CSV']]
   (<определение столбца> [, { <определение столбца> | <ограничение таблицы>}...])
   [ON COMMIT {DELETE | PRESERVE} ROWS]
   [SQL SECURITY {DEFINER | INVOKER}];
   [[IN] TABLESPACE {<имя табличного пространства> | PRIMARY}];

<определение столбца> ::= { <опр-е обычного столбца>
                          | <опр-е вычисляемого столбца>
                          | <опр-е идентификационного столбца> }

<определение обычного столбца> ::=
             <имя столбца> { <тип данных> | <имя домена>}
             [DEFAULT {<литерал> | NULL | <контекстная переменная>}]
             [NOT NULL]
             [<ограничение столбца>]
             [COLLATE <порядок сортировки>]

<определение вычисляемого столбца> ::=
             <имя столбца> [<тип данных>]
             {COMPUTED [BY] | GENERATED ALWAYS AS} (<выражение>)

<определение идентификационного столбца> ::=
       <имя столбца> [<тип данных>]
       GENERATED {ALWAYS|BY DEFAULT} AS IDENTITY [(<опции ав.> [<опции ав.>])]
       [<ограничение столбца>]

<опции автоинкремента> ::= START WITH <начальное значение>
                         | INCREMENT [BY] <приращение>

<ограничение столбца> ::=
  [CONSTRAINT <имя ограничения>]
  { UNIQUE [<предложение USING>] [[IN] TABLESPACE {<имя табл.пространства>|PRIMARY}]
  | PRIMARY KEY [<предложение USING>] [[IN] TABLESPACE {<имя табл.прос-ва>|PRIMARY}]
   | REFERENCES <имя таблицы> [(<имя столбца>)]
      [ON DELETE { NO ACTION | CASCADE | SET DEFAULT | SET NULL }]
      [ON UPDATE { NO ACTION | CASCADE | SET DEFAULT | SET NULL }]
      [<предложение USING>] [[IN] TABLESPACE { <имя табл. пространства> | PRIMARY}]
   | CHECK (<условие столбца>)
   }

<ограничение таблицы> ::=
   [CONSTRAINT <имя ограничения>]
   { UNIQUE (<столбец> [, <столбец>...]) [<предложение USING>]
        [[IN] TABLESPACE { <имя табличного пространства> | PRIMARY}]
   | PRIMARY KEY (<столбец> [, <столбец>...]) [<предложение USING>]
        [[IN] TABLESPACE { <имя табличного пространства> | PRIMARY}]
   | FOREIGN KEY (<столбец> [, <столбец>...])
      REFERENCES <имя таблицы> [(<столбец> [, <столбец>...])]
      [ON DELETE { NO ACTION | CASCADE | SET DEFAULT | SET NULL }]
      [ON UPDATE { NO ACTION | CASCADE | SET DEFAULT | SET NULL }]
      [<предложение USING>] [[IN] TABLESPACE { <имя табл. пространства> | PRIMARY}]
   | CHECK (<условие столбца>)
}

<предложение USING> ::= USING [ASC[ENDING] | DESC[ENDING]] INDEX <имя индекса>

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

Столбец должен иметь имя, уникальное только в данной таблице. В других таблицах могут присутствовать столбцы с тем же именем.

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

Примечание

Создать новую таблицу может администратор и пользователь с привилегией CREATE TABLE.

Пользователь, создавший таблицу, становится её владельцем.

Глобальные временные таблицы (GTTs)

Глобальные временные таблицы (Global Temporary Tables, GTTs) так же, как и обычные таблицы, являются постоянными метаданными, но данные в них ограничены по времени существования транзакцией (значение по умолчанию) или соединением с БД. Каждая транзакция или соединение имеет свой собственный экземпляр GTT с данными, изолированный от всех остальных. Экземпляры создаются только при условии обращения к GTT, и данные в ней удаляются при подтверждении транзакции или отключении от БД. Для изменения или удаления метаданных GTT можно использовать конструкции ALTER TABLE и DROP TABLE. Синтаксис создания временной таблицы представлен ниже:

Листинг 10.2 Синтаксис оператора создания глобальной временной таблицы

CREATE GLOBAL TEMPORARY TABLE <имя таблицы>
   (<определение столбца> [, {<определение столбца> | <ограничение таблицы>}...])
   [ON COMMIT {DELETE | PRESERVE} ROWS]
   [SQL SECURITY {DEFINER | INVOKER}];

Если в операторе создания глобальной временной таблицы указано необязательное предложение ON COMMIT DELETE ROWS, то будет создана GTT транзакционного уровня (по умолчанию). При указании предложения ON COMMIT PRESERVE ROWS будет создана GTT уровня соединения с базой данных.

Примечание

Предложение EXTERNAL [FILE] нельзя использовать для глобальной временной таблицы.

Глобальные временные таблицы имеют ряд ограничений:

  • GTT и обычные таблицы не могут ссылаться друг на друга;

  • GTT уровня соединения (PRESERVE ROWS) не могут ссылаться на GTT транзакционного уровня (DELETE ROWS);

  • Уничтожения экземпляра GTT в конце своего жизненного цикла не вызывает срабатывания триггеров до/после удаления

  • Ограничения домена не могут ссылаться на временные таблицы.

В системном каталоге временные таблицы отличаются друг от друга и от постоянных таблиц значением типа RDB$RELATION_TYPE в системной таблице RDB$RELATIONS:

  • GTT уровня соединения (PRESERVE ROWS) имеет тип RDB$RELATION_TYPE = 4

  • GTT транзакционного уровня (DELETE ROWS) имеет тип RDB$RELATION_TYPE = 5

Пример создания глобальной временной таблицы уровня соединения:

CREATE GLOBAL TEMPORARY TABLE MyConnGTT (
   id INTEGER NOT NULL PRIMARY KEY,
   txt VARCHAR(32),
   ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP )
ON COMMIT PRESERVE ROWS;

Пример создания глобальной временной таблицы уровня транзакции, ссылающейся внешним ключом на глобальную временную таблицу уровня соединения:

CREATE GLOBAL TEMPORARY TABLE MyTrGTT (
   id INTEGER NOT NULL PRIMARY KEY,
   parent_id INT NOT NULL REFERENCES MyConnGTT(id),
   txt VARCHAR(32),
   ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP );

Использование внешних файлов

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

СУБД РЕД База Данных поддерживает два формата внешних файлов: формат «строк» c фиксированной длиной и .csv формат.

Столбцы таблицы, которые хранятся во внешних файлах, могут быть любого типа данных, кроме BLOB. Недопустимо также использование массивов с любым типом данных.

Над таблицей, хранящейся во внешнем файле, допустимы только операции выборки (SELECT) данных и добавления новых строк (INSERT). Операторы INSERT добавляют в конец существующего внешнего файла новые строки. Для .csv формата допустима только выборка данных. Операции же изменения существующих данных (UPDATE) или удаления строк такой таблицы (DELETE) не могут быть выполнены. Попытки их выполнения вызовут исключения базы данных.

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

Возможность использования для таблиц внешних файлов зависит от установки значения параметра ExternalFileAccess в файле конфигурации firebird.conf. По умолчанию этот параметр имеет значение None, что запрещает использование для таблиц любой базы данных внешних файлов. Если параметр ExternalFileAccess содержит Restrict, то файл внешней таблицы должен находится в одном из каталогов, указанных в качестве аргумента Restrict.

Файлы с фиксированной длиной строк

Внешняя таблица, находящаяся в таком файле, имеет формат «строк» c фиксированной длиной. Нет никаких разделителей полей: границы полей и строк определяются максимальными размерами в байтах в определении каждого поля. Это необходимо помнить и при определении структуры внешней таблицы, и при проектировании входного файла для внешней таблицы, в которую должны импортироваться данные из другого приложения.

Если при обращении к внешней таблице РЕД База Данных не находит файла, то она создаёт его при первом обращении. Последующие операторы INSERT добавляют в конец существующего файла новые записи. Если записанные перед созданием таблицы данные в этом файле не соответствуют по структуре создаваемой таблице, то в дальнейшем при использовании таблицы обязательно возникнут проблемы.

Самым полезным типом данных для столбцов внешних таблиц является тип CHAR с фиксированной длиной, длина должна подходить под данные с которыми необходимо работать. Числовые типы и даты легко преобразуются в них.

Если данные читаются базой данных РЕД Базы Данных, то в то же время они могут оказаться нераспознаваемыми дня внешних приложений и являться для них «абракадаброй».

Конечно, существуют способы манипулирования типами данных так, чтобы создавать выходные файлы из РЕД Базы Данных, которые могут быть непосредственно прочитаны как входные файлы в других приложениях, используя хранимые процедуры с использованием внешних таблиц или без них. Описания этих методов выходит за рамки данного руководства. Здесь мы приведём лишь некоторые рекомендации и советы для создания и работы с простыми текстовыми файлами, поскольку внешняя таблица часто используется как простой способ для создания или чтения транзакционно-независимого журнала. Эти файлы могут быть прочитаны в оффлайн режиме текстовым редактором или приложением аудита.

Как правило, внешние файлы более удобны если строки разделены разделителем, в виде последовательности "новой строки", которая может быть распознана приложением на предназначенной платформе. Для Windows — это двухбайтная CRLF последовательность: возврат каретки (ASCII код 13) и перевод строки (ASCII код 10). Для POSIX — LF обычно самодостаточен, в некоторых MacOS X приложениях она может быть LFCR.

Пример.

Создадим внешнюю таблицу, которая содержит всего два столбца: метку времени и текстовое сообщение. Третий столбец хранит разделитель строки.

Существуют различные способы для автоматического заполнения столбца разделителя. В нашем примере это сделано с помощью BEFORE INSERT триггера и встроенной функции ASCII_CHAR.

CREATE TABLE ext_log
EXTERNAL FILE 'd:\externals\log_me.txt' (
   stamp CHAR(38),
   message CHAR(100),
   crlf CHAR(2) -- Для Windows
);

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

CREATE TRIGGER bi_ext_log FOR ext_log
ACTIVE BEFORE INSERT
AS BEGIN
   IF (NEW.stamp IS NULL) THEN
       NEW.stamp = CAST (CURRENT_TIMESTAMP AS CHAR(38));
   NEW.crlf = ASCII_CHAR(13) || ASCII_CHAR(10);
END!

Вставка некоторых записей (это может быть сделано в обработчике исключения):

INSERT INTO ext_log (message) VALUES('Shall I compare thee to a summer''s day?');
INSERT INTO ext_log (message) VALUES('Thou art more lovely and more temperate');

Содержимое внешнего файла:

2024-06-03 10:11:05.0200 Europe/Moscow Shall I compare thee to a summer's day?
2024-06-03 10:11:05.0200 Europe/Moscow Thou art more lovely and more temperate

Файлы формата CSV

В СУБД РЕД База Данных реализован CSV адаптер внешних таблиц, позволяющий импортировать данные из файлов CSV. Использовать CSV-файлы для создания внешних таблиц можно с помощью предложения EXTERNAL [FILE] '<спецификация файла>' ADAPTER 'CSV' в операторе создания таблицы.

Как уже было сказано, для внешней таблицы в .csv формате допустима только операция выборки данных. Для редактирования CSV-файлов нужно использовать сторонние программы.

Каждая строка в CSV файле соответствует строке таблицы. Пустые строки игнорируются. В качестве разделителя значений полей используется запятая (',') без пробелов.

Количество значений в строках файла, разделенных запятыми, может не соответствовать количеству полей таблицы. Если значений меньше, то оставшиеся поля будут установлены в NULL. Если значений больше, то лишние значения проигнорируются. Если значение пропущено (например, value1,value2,,value4), то соответствующее поле также будет установлено в NULL.

Если значение по какой-либо причине не может быть cконвертировано в требуемый тип поля, то будет выброшено исключение.

Значения, содержащие зарезервированные символы (двойная кавычка, запятая, новая строка) обрамляются двойными кавычками (например, value1,"one,two,three",value3). Если в значении встречаются кавычки — они представляются в файле в виде двух кавычек подряд (например, value1,"one,""two"",three",value3).

Пример.

Пусть в CSV файле содержатся следующие строки:

01/03/1997,TESCO,"EVERY
LITTLE HELPS"
10/05/1967,M&M,"MELTS IN YOUR MOUTH, NOT IN YOUR HANDS"
06/23/1954,Disneyland,"I'm going to ""Walt Disney World""!"
07/15/1934,,JUST DO IT,aaa,bbb
,

Пример использования CSV адаптера:

create table CSV_EXT external 'D:\externals\table.csv' adapter 'CSV' (
   Sdate DATE,
   Company VARCHAR(14),
   Slogan VARCHAR(50)
);

Выборка из таблицы будет иметь такой вид:

SELECT * FROM CSV_EXT;

SDATE      COMPANY        SLOGAN
========== ============== ======================================
1997-01-03  TESCO          EVERY
                           LITTLE HELPS
1967-10-05  M&M            MELTS IN YOUR MOUTH, NOT IN YOUR HANDS
1954-06-23  Disneyland     I'm going to "Walt Disney World"!
1934-07-15  <null>         JUST DO IT
<null> <null>         <null>

Задание типа данных

Подробное описание типов данных, допустимых операций преобразования и других встроенных в SQL функций работы с данными см. в главе 4 и в 36. Синтаксис задания типа данных столбца таблицы показан в листинге .

Листинг 10.3 Синтаксис задания типа данных столбца таблицы

<тип данных> ::= {
     {SMALLINT | INTEGER | BIGINT} [<размерность массива>]
   | BOOLEAN [<размерность массива>]
   | {FLOAT | DOUBLE PRECISION} [<размерность массива>]
   | DECFLOAT[({16 | 34})]
   | {DATE | TIME | TIMESTAMP} [<размерность массива>]
   | {DECIMAL | NUMERIC} [(<точность> [ ,<масштаб>])] [<размерность массива>]
   | {CHAR | CHARACTER | CHARACTER VARYING | VARCHAR} [(<размер>)]
       [<размерность массива>] [CHARACTER SET <набор символов>]
   | {NCHAR | NATIONAL CHARACTER | NATIONAL CHAR} [VARYING]
       [(<размер>)] [<размерность массива>]
   | BLOB [SUB_TYPE { <номер подтипа> | <имя подтипа>}]
       [SEGMENT SIZE <длина сегмента>] [CHARACTER SET <набор символов>]
   | BLOB [(<размер сегмента> [, <номер подтипа>])]
}

<размерность массива> ::= [[<целое 1>:]<целое 2> [, [<целое 1>:]<целое 2>...]]

Для столбца с любым типом данных, кроме BLOB, можно указать размерность массива, если этот столбец является массивом. Для массива задается начальный номер элемента в массиве (положительное число «целое 1») и через двоеточие последний номер элемента («целое 2»). Если указано только одно число, то оно означает последний номер в элементе массива, а первым номером считается 1. Если массив многомерный, то через запятую указываются и другие пары элементов. Размерность задается в квадратных скобках.

При описании символьного столбца с типами CHAR, VARCHAR и BLOB с подтипом TEXT можно в предложении CHARACTER SET указать набор символов, если требуется набор, отличный от набора символов по умолчанию, установленного для всей базы данных. Если же при создании базы данных не был указан набор символов, то по умолчанию принимается набор символов NONE. В этом случае данные хранятся и извлекаются, так как они были поданы. В столбец можно загружать данные в любой кодировке, но невозможно загрузить эти данные в столбец с другой кодировкой. Транслитерация между исходными и конечными кодировками не выполняется, что может приводить к ошибкам.

Кроме того, в предложении COLLATE можно задать и порядок сортировки (для типа данных BLOB использование COLLATE недопустимо). Если порядок сортировки не указан, то по умолчанию принимается порядок сортировки по умолчанию для указанного набора символов.

Для типа данных BLOB можно указывать подтип (SUB_TYPE) и размер сегмента (SEGMENT SIZE). Существует два варианта синтаксиса для задания подтипа и размера сегмента:

BLOB [SUB_TYPE { <номер подтипа> | <имя подтипа>}]
     [SEGMENT SIZE <длина сегмента>] [CHARACTER SET <набор символов>]

и

BLOB [(<размер сегмента> [, <номер подтипа>])]

Размер сегмента задается в байтах. Он не может превышать 65535.

Использование ссылки на домен

Если вместо типа данных задается имя домена, то все его характеристики копируются для этого столбца. Если далее в описании столбца заданы и другие характеристики, то они заменяют скопированные характеристики из домена.

Если определение столбца основано на домене, оно может включать новое значение по умолчанию, дополнительные ограничения CHECK, предложение COLLATE, которые перекрывают значения указанные при определении домена. Определение такого столбца может включать дополнительные ограничения столбца, например NOT NULL, если домен его ещё не содержит.

Предупреждение

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

Значение по умолчанию

Необязательное предложение DEFAULT определяет значение по умолчанию для столбца — это то значение, которое будет присвоено столбцу, если при добавлении новой строки в таблицу в операторе INSERT не указан данный столбец и его значение. Это же значение по умолчанию будет присвоено столбцу при использовании оператора INSERT с предложением DEFAULT VALUES (см. главу 12). Значение по умолчанию применяется только при выполнении оператора добавления данных INSERT и не оказывает никакого влияния на выполнение оператора изменения существующих в таблице данных (UPDATE). Если в операторе изменения данных не указан какой-либо столбец, то его значение просто не изменяется.

Значением по умолчанию может быть литерал, пустое значение NULL или контекстная переменная. Литералом может быть любая самоопределенная константа соответствующего типа данных, предварительно определенный литерал или контекстная переменная SQL (подробности использования и преобразования предварительно определенных литералов и контекстных переменных см. в главе 4). Если значение по умолчанию в операторе описания столбца явно не устанавливается, то подразумевается пустое значение NULL.

Использование каких-либо выражений в значении по умолчанию недопустимо.

Пример.

Следующий столбец типа DATE имеет значением по умолчанию текущую дату на сервере (CURRENT_DATE) — дату на серверном компьютере в то время, когда выполняется данный оператор INSERT:

DATE_C DATE DEFAULT CURRENT_DATE

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

Значение NOT NULL

Необязательное предложение NOT NULL указывает, что столбцу не может быть присвоено пустое значение в операторе INSERT или UPDATE. Это предложение является обязательным для столбца, входящего в состав первичного ключа таблицы. Такое предложение для первичного ключа требуется явно указать даже в том случае, если на основании условий столбца или условий таблицы (см. далее) такому столбцу не может быть присвоено пустое значение.

Пример.

Пусть в базе данных существует справочная таблица, содержащая сведения о странах:

/*** Справочник стран ***/
CREATE TABLE COUNTRY (
    CODCOUNTRY CHAR(3) NOT NULL,    /* Код страны */
    NAME CHAR(30),                  /* Краткое название страны */
    FULLNAME CHAR(60),              /* Полное название страны */
    CAPITAL CHAR(15),               /* Название столицы */
    DESCR BLOB,                     /* Дополнительное описание */
    CONSTRAINT PK_COUNTRY PRIMARY KEY (CODCOUNTRY)
);

Здесь код страны является первичным ключом. По этой причине он объявлен с предложением NOT NULL.

Ограничения

Существуют четыре вида ограничений:

  • первичный ключ (PRIMARY KEY);

  • уникальный ключ (UNIQUE);

  • внешний ключ (REFERENCES или FOREIGN KEY);

  • проверочное ограничение (CHECK).

Ограничения могут быть указаны на уровне столбца («ограничения столбцов») или на уровне таблицы («табличные ограничения»). Ограничения уровня таблицы необходимы, когда ключи (ограничение уникальности, первичный ключ или внешний ключ) должны быть сформированы по нескольким столбцам, или, когда ограничение CHECK включает несколько столбцов, т.е. действует на уровне записи. Синтаксис для некоторых типов ограничений может незначительно отличаться в зависимости от того определяется ограничение на уровне столбца или на уровне таблицы.

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

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

  • Вы можете смешивать ограничения столбцов и ограничения таблиц в одном операторе CREATE TABLE.

Системой автоматически создаётся индекс для первичного ключа (PRIMARY KEY), уникального ключа (UNIQUE KEY) и внешнего ключа (REFERENCES для ограничения уровня столбца, и FOREIGN KEY REFERENCES для ограничения уровня таблицы).

Именованные ограничения

Имя ограничения можно задать явно, если указать его в необязательном предложении CONSTRAINT. Рекомендуется задавать осмысленные имена ограничениям столбца. В дальнейшем при изменении характеристик таблицы к таким ограничениям будет проще обращаться по заданному имени. Имя ограничения должно быть уникальным среди имен всех ограничений столбцов и/или имен ограничений таблиц во всех таблицах базы данных, а также среди имен созданных пользователем индексов.

По умолчанию имя индекса ограничения будет тем же самым, что и самого ограничения. Если для индекса необходимо задать другое имя, то его можно указать в предложении USING.

Имена для ограничений и их индексов

Если имя ограничения не задано, то оно автоматически будет сгенерировано системой.

Ограничения уровня столбца и их индексы автоматически именуются следующим образом:

  • Имена ограничений имеют следующий вид INTEG_n, где n представлено одним или несколькими числами;

  • Имена индексов имеют вид RDB$PRIMARYn (для индекса первичного ключа), RDB$FOREIGNn (для индекса внешнего ключа) или RDB$n (для индекса уникального ключа), где n представлено одним или несколькими числами;

Схемы автоматического формирования имён для ограничений уровня таблицы и их индексов одинаковы.

Предложение USING

Предложение USING позволяет задать имя индекса для поддержания соответствующего ограничения первичного, уникального или внешнего ключа и указать его упорядоченность — по возрастанию значений реквизитов ключа (ASCENDING) или по убыванию их значений (DESCENDING). Если упорядоченность не задана, то предполагается ASCENDING, по возрастанию. Если индекс не указан (не задано предложение USING), то автоматически будет создан индекс с именем этого ограничения, если указано имя ограничения, или с системным именем, если не было задано имени ограничения в предложении CONSTRAINT. Для ограничения CHECK это предложение не применимо.

Примечание

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

Ограничение UNIQUE

Ограничение UNIQUE определяет уникальный ключ, это означает, что при помещении в таблицу новой строки или при изменении значений существующей в таблице строки значение столбца, являющегося уникальным ключом, должно быть уникальным в таблице — в таблице не должно существовать двух разных строк, имеющих одно и то же значение такого столбца. Исключением из этого правила является только тот случай, когда уникальный ключ имеет пустое значение NULL (если в описании столбца не указано NOT NULL). Таких строк с пустым значением уникального ключа в таблице может быть произвольное количество.

Для уникального ключа система автоматически строит соответствующий индекс. Если в описании уникального ключа было указано и имя этого ограничения в предложении CONSTRAINT, то это имя будет присвоено индексу (если в предложении USING не было задано другого имени), иначе индекс получит системное имя.

В таблице может существовать произвольное количество уникальных ключей.

Ограничение уникальности может быть определено на нескольких столбцах. В этом случае вы должны определять его как ограничение уровня таблицы.

Уникальный ключ может принимать участие в связке внешний ключ/уникальный ключ для поддержания ссылочной целостности данных (предложение REFERENCES ограничения столбца или предложение FOREIGN KEY ограничения таблицы в подчиненной таблице).

Нельзя в базе данных явно создавать индекс, по структуре соответствующий уникальному ключу (см. главу 15). Такое поведение может привести к аварийному завершению работы сервера базы данных при выборке данных на основании каких-либо условий, включающих использование уникального ключа.


NULL в уникальных ключах

Согласно стандарту SQL-99 РЕД База Данных допускает одно или более значений NULL в столбце на который наложено ограничение UNIQUE. Это позволяет определить ограничение UNIQUE на столбцах, которые не имеют ограничения NOT NULL.

Для уникальных ключей, содержащих несколько столбцов, логика немного сложнее:

  • Разрешено множество записей со значением NULL во всех столбцах ключа;

  • Разрешено множество записей с различными комбинациями null и not-null значений в ключах;

  • Разрешено множество записей, в которых в одном из столбцов уникального ключа содержится значение NULL, а остальные столбцы заполнены значениями и эти значения различны хотя бы в одном из них;

Это можно резюмировать следующим примером:

RECREATE TABLE t( x int, y int, z int, unique(x,y,z));
INSERT INTO t values( NULL, 1, 1 );
INSERT INTO t values( NULL, NULL, 1 );
INSERT INTO t values( NULL, NULL, NULL );
INSERT INTO t values( NULL, NULL, NULL );        
INSERT INTO t values( NULL, NULL, 1 );           

Ограничение PRIMARY KEY

Ограничение PRIMARY KEY определяет первичный ключ. В отличие от уникального ключа в таблице может быть только один первичный ключ.

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

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

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

Примечание

Первичный ключ по единственному столбцу может быть определён как на уровне столбца, так и на уровне таблицы.

Первичный ключ по нескольким столбцам может быть определён только на уровне таблицы.

Для первичного ключа система также автоматически строит индекс. Если в описании первичного ключа было указано имя ограничения в предложении CONSTRAINT (что рекомендуется), то это имя будет присвоено индексу, если еще и в предложении USING не было задано другого имени.

Нельзя в базе данных создавать индекс, по структуре соответствующий первичному ключу (см. главу 15). Это может привести к аварийному завершению работы сервера базы данных при выборке данных на основании каких-либо условий, включающих использование значений первичного ключа, а также в случае, когда в плане выборки используется первичный ключ.


Использование первичных ключей

Система управления базами данных РЕД База Данных не требует обязательного присутствия в каждой таблице базы данных первичного ключа, однако наличие в таблицах первичных ключей очень желательно. Кроме того, стандарт SQL-92 требует обязательного существования для каждой таблицы первичного ключа.

Для таблицы стран, например, первичным ключом является код страны, значение которого вводит пользователь. Таблица регионов страны содержит первичный ключ, состоящий из двух столбцов — из кода страны и кода региона, что является естественным, поскольку между этими таблицами существует чисто иерархическая связь. Код страны в этом случае при добавлении новой строки в таблицу регионов может выбираться из таблицы стран, а код региона создается пользователем. Если нужна таблица, содержащая список районов региона, то для нее можно использовать первичный ключ уже из трех столбцов — код страны, код региона, код района.

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

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

Иными словами, варианты выбора столбцов таблицы для включения в состав первичного ключа не всегда являются очевидными. Во многих случаях хорошим решением будет создание искусственного первичного ключа. Для этого в таблицу добавляется целочисленный столбец, первичный ключ, которому при помещении в таблицу новой строки присваивается уникальное числовое значение, получаемое из объекта базы данных генератор. Для получения нового значения из генератора используется внутренняя функция GEN_ID или конструкция NEXT VALUE FOR.

Обычно для столбца искусственного первичного ключа выбирается тип данных INTEGER. Если таблица содержит небольшое количество записей, которые редко изменяются, то можно использовать и тип данных SMALLINT. Когда же в таблице присутствует очень много строк, которые к тому же часто изменяются (одни удаляются, новые добавляются), то имеет смысл использовать даже и тип данных BIGINT. В большинстве случаев для искусственного первичного ключа все же используется тип данных INTEGER.

Пусть, например, существует таблица, хранящая данные по людям, PEOPLE. Для нее было принято решение использовать искусственный первичный ключ — целочисленный столбец PEOPLE_ID с типом данных INTEGER. Создан также генератор GEN_PEOPLE. Тогда добавить новую строку в эту таблицу можно, например, следующим образом:

INSERT INTO PEOPLE (PEOPLE_ID, ...)
       VALUES (GEN_ID(GEN_PEOPLE, 1), ...);

Для получения значения искусственного первичного ключа здесь происходит обращение к генератору. В операторе добавления новой строки при обращении к функции GEN_ID вначале текущее значение генератора увеличивается на единицу, а затем это новое значение присваивается первичному ключу новой записи.

В РЕД Базе Данных существует конструкция NEXT VALUE FOR. При ее использовании значение генератора увеличивается в точности на единицу. Эту конструкцию рекомендуется использовать вместо функции GEN_ID(). Предыдущий оператор можно записать и в следующем виде:

INSERT INTO PEOPLE (PEOPLE_ID, ...)
       VALUES (NEXT VALUE FOR GEN_PEOPLE, ...);

Ограничение FOREIGN KEY, REFERENCES

Внешний ключ должен иметь пустое значение NULL или же он должен ссылаться на первичный или уникальный ключ (родительский ключ) другой или той же самой таблицы. Понятие «ссылается» означает только лишь, что в родительской таблице должна присутствовать строка, имеющая такое же значение первичного или уникального ключа, что и внешний ключ дочерней таблицы. Ограничение внешнего ключа гарантирует, что столбец (столбцы) участник может содержать только те значения, которые существуют в указанном столбце (столбцах) родительской таблицы.

Первичный или уникальный ключ часто называют родительскими ключами.

На уровне столбца ограничение внешнего ключа определяется с использованием ключевого слова REFERENCES:

<ограничение столбца> ::=
   [ CONSTRAINT <имя ограничения> ]
   {   UNIQUE [<предложение USING>]
     | PRIMARY KEY [<предложение USING>]
     | REFERENCES <имя таблицы> [(<имя столбца>)] [<предложение USING>]
         [ON DELETE { NO ACTION | CASCADE | SET DEFAULT | SET NULL }]
         [ON UPDATE { NO ACTION | CASCADE | SET DEFAULT | SET NULL }]
     | CHECK (<условие столбца>)
   }

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

На уровне таблицы могут быть определены внешний ключ над одним или несколькими столбцами. Внешние ключи над несколькими столбцами можно определить только на уровне таблицы.

<ограничение таблицы> ::=
   [CONSTRAINT <имя ограничения>]
   {   UNIQUE (<столбец> [, <столбец>...]) [<предложение USING>]
     | PRIMARY KEY (<столбец> [, <столбец>...]) [<предложение USING>]
     | FOREIGN KEY (<столбец> [, <столбец>...])
     | REFERENCES <имя таблицы> [(<столбец> [, <столбец>...])] [<предложение USING>]
         [ON DELETE { NO ACTION | CASCADE | SET DEFAULT | SET NULL }]
         [ON UPDATE { NO ACTION | CASCADE | SET DEFAULT | SET NULL }]
     | CHECK (<условие столбца>)
   }

Синтаксис определения внешнего ключа на уровне таблицы несколько отличается. После определения всех столбцов, с их ограничения уровня столбца, вы можете определить именованное ограничение внешнего ключа уровня таблицы, используя ключевые слова FOREIGN KEY и имён столбцов для которых оно применяется.

Имена столбцов в главной таблице могут отличаться от тех, что указаны во внешнем ключе.

Примечание

Если целевые столбцы не указаны, то внешний ключ автоматически ссылается на столбцы первичного ключа целевой таблицы.


Действия внешнего ключа

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

  • Предложение ON DELETE определяет, что произойдет с записями дочерней таблицы при удалении соответствующей строки главной таблицы. Если это предложение отсутствует, то будет установлено RESTRICT. Это означает, что из родительской таблицы нельзя удалить строку, для которой существуют строки в дочерней таблице, внешние ключи которых ссылаются на первичный (уникальный) ключ удаляемой строки.

  • Предложение ON UPDATE определяет, что произойдет с записями дочерней таблицы при изменении значения первичного/уникального ключа в строке родительской таблицы. Если это предложение отсутствует, то будет установлено RESTRICT. Это означает, что в родительской таблице нельзя изменить значение первичного (уникального) ключа, если в дочерней таблице существуют строки, внешние ключи которых ссылаются на первичный (уникальный) ключ изменяемой строки.

Для обеспечения ссылочной целостности внешнего ключа, когда изменяется или удаляется значение связанного первичного или уникального ключа, могут быть выполнены следующие действия:

  • NO ACTION — не будет выполнено никаких действий (значение по умолчанию). Обеспечение соответствия внешнего ключа первичному (уникальному) ключу должна выполнить сама клиентская программа, либо для этого следует написать выполняемую хранимую процедуру, к которой должно осуществляться обращение из клиентской программы в процессе удаления или изменения строки, или специально созданный пользовательский триггер до удаления (BEFORE DELETE) или до изменения (BEFORE UPDATE), выполняющий все необходимые установки значений внешнего ключа дочерней таблицы;

  • CASCADE — при выполнении удаления (изменения) строки в главной таблице в дочерней таблице должны быть автоматически удалены (обновлены) все записи, имеющие те же значения внешнего ключа, что и значение первичного (уникального) родительского ключа удаляемой (изменяемой) строки родительской таблицы. Реализацию такого поведения выполняет автоматически созданный системный триггер. От пользователя в таком случае не требуется выполнения никаких дополнительных действий;

  • SET DEFAULT — столбец внешнего ключа всех соответствующих строк в дочерней таблице устанавливается в значение по умолчанию, определенное в предложении DEFAULT этого столбца, описанного как внешний ключ. В подобной ситуации, как правило, в клиентской программе следует предпринять дополнительные меры по обеспечению непротиворечивости данных. Если значение по умолчанию для столбца внешнего ключа не задано, то столбцу присваивается значение NULL;

  • SET NULL — значения внешнего ключа всех соответствующих строк в дочерней таблице устанавливаются в пустое значение NULL. Это не приведет к нарушению целостности данных, так как для внешнего ключа допустимо пустое значение.

Реализация поведения системы при удалении строки или изменении значения первичного (уникального) родительского ключа главной таблицы (за исключением задания варианта NO ACTION) осуществляется автоматически создаваемыми системными триггерами.

Для внешнего ключа система также автоматически строит индекс.

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

Ограничение CHECK

Ограничение CHECK определяет условие, которому должно удовлетворять значение, помещаемое в данный столбец. Условие в предложении CHECK также иногда называется предикатом. Это логическое выражение, которое может возвращать значения TRUE (истина), FALSE (ложь) и UNKNOWN (неопределенное, неизвестное значение). Значение UNKNOWN обычно является результатом логических операций, где один из операндов имеет пустое значение NULL. Подробнее обо всех предикатах рассказано в главе 3.

Условие считается выполненным, то есть значение, помещаемое в столбец, допустимо, если предикат возвращает значение TRUE.

Такое условие может быть достаточно сложным. Это условие используется как при добавлении в таблицу новой строки (оператор INSERT), так и при изменении существующего значения столбца строки таблицы (оператор UPDATE), а также операторов, в которых может произойти одно из этих действий (UPDATE OR INSERT, MERGE). Для обеспечения выполнения условий ограничения автоматически создается системный триггер. Синтаксис условия столбца таблицы представлен в листинге .

Листинг 10.4 Синтаксис задания условия столбца таблицы

<условие столбца> ::= {
         <значение> <оператор сравнения> {<значение> | (<выбор одного>)}
       | <значение> [NOT] IN ({<значение> [, <значение> ...] | <поиск одного>})
       | <значение> [NOT] BETWEEN <значение> AND <значение>
       | <значение> [NOT] LIKE <шаблон> [ESCAPE '<символ>']
       | <значение> [NOT] SIMILAR TO <значение> [ESCAPE <значение>]
       | <значение> IS [NOT] NULL
       | <значение> IS [NOT] DISTINCT FROM <значение>
       | <значение> <оператор сравнения> {ALL | SOME | ANY} (<поиск одного>)
       | [NOT] EXISTS (<поиск многих>)
       | [NOT] SINGULAR (<поиск многих>)
       | <значение> [NOT] CONTAINING <значение>
       | <значение> [NOT] STARTING [WITH] <значение>
       | (<условие столбца>)
       | NOT <условие столбца>
       | <условие столбца> OR <условие столбца>
       | <условие столбца> AND <условие столбца>
}

<значение> ::= {
         <имя столбца> [[<элемент массива> [, <элемент массива> ...]]]
       | <литерал>
       | <контекстная переменная>
       | <выражение>
       | NEXT VALUE FOR <имя генератора>
       | GEN_ID(<имя генератора>, <значение>)
       | CAST(<значение> AS <тип данных>)
       | (<выбор одного>)
       | <обычная внутренняя функция> (<параметры>)
       | <агрегатная функция в операторе SELECT>
       | <функция UDF> [(<параметр> [, <параметр>]...)]
       | NULL }

Выбор одного — это оператор SELECT, возвращающий в точности одно значение одного столбца, получаемое из таблицы, представления или в качестве выходного параметра хранимой процедуры выбора. Пустое значение недопустимо.

Поиск одного — оператор SELECT, возвращающий произвольное количество значений одного столбца. Здесь возможно пустое значение.

Поиск многих — оператор SELECT, возвращающий ноль или произвольное количество значений нескольких столбцов.

Предупреждение

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

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

Нумерация столбцов

При создании таблицы происходит неявная нумерация столбцов. Первый создаваемый столбец получает номер один, следующий — номер два и т.д. Вообще говоря, порядок столбцов в таблице особого значения не имеет за исключением случая, когда в операторе добавления данных INSERT не задан явно список столбцов. Тем не менее, для любого столбца таблицы можно изменить номер — переместить его с одной позиции на другую. Об изменении позиции столбца см. ниже в этой главе в разделе 10.2.

Вычисляемые столбцы

Вычисляемый столбец задается предложением:

<имя столбца>  [<тип данных>] {COMPUTED [BY] | GENERATED ALWAYS AS} (<выражение>)

COMPUTED [BY] или GENERATED ALWAYS AS (согласно стандарту SQL-2003) эквивалентны по смыслу.

Значение такого столбца не хранится в таблице, а вычисляется, создается, при выборке данных из таблицы. Термин «вычисляемый» не обязательно означает только лишь арифметическое вычисление. Для строковых данных, например, может применяться операция конкатенации, вызов функции получения подстроки и ряда других встроенных функций.

Выражение в этом предложении — выражение, возвращающее ровно одно значение любого типа данных, кроме BLOB или массива. Выражение может содержать любые допустимые операции, обращение к встроенным функциям и/или к функциям, определенным пользователем, UDF (см. 34). Среди значений выражения допустимо использование и оператора SELECT, заключенного в круглые скобки, который при обращении к таблице (это может быть другая или та же самая таблица), представлению или хранимой процедуре выбора возвращает единственное значение или NULL. Операндами используемых в выражении операторов и функций могут быть различные константы, контекстные переменные и имена столбцов этой же таблицы. Все столбцы, используемые в выражении, должны быть определены ранее в этой таблице. Все таблицы, представления и хранимые процедуры, к которым обращаются операторы SELECT, должны уже существовать в базе данных. По этой причине вычисляемые столбцы обычно описывают в самом конце таблицы после ограничений таблицы или непосредственно перед ними. Еще один способ задания вычисляемых столбцов — добавление их в уже существующую таблицу при помощи оператора ALTER TABLE (см. далее), когда все таблицы, представления и хранимые процедуры базы данных уже описаны в системе.

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

Пример 1. Пусть в таблице существует столбец «оклад человека», SALARY. Можно создать вычисляемый столбец с именем NET_SALARY, который будет иметь значение на 13% меньше, чем оклад (вычеты из заработной платы):

CREATE TABLE STAFF (
    ...
    SALARY DECIMAL(8, 2),
    NET_SALARY COMPUTED BY (SALARY * 0.87)
);

Вычисляемому столбцу NET_SALARY системой будет присвоен тип данных NUMERIC(18, 4). При выборке данных из этой таблицы оператором SELECT будет возвращаться и значение вычисляемого столбца, на 13 процентов меньшее, чем указанный оклад.

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

CREATE TABLE FIRM (
    COD INTEGER NOT NULL,
    NAME1 CHAR(50),
    CODCOUNTRY CHAR(3),
    COUNTRYNAME COMPUTED BY ((SELECT NAME
                              FROM COUNTRY
                              WHERE COUNTRY.CODCOUNTRY = FIRM.CODCOUNTRY)),
    FULLCOUNTRYNAME COMPUTED BY ((SELECT FULLNAME
                                  FROM COUNTRY
                                  WHERE COUNTRY.CODCOUNTRY = FIRM.CODCOUNTRY))
);

В этой таблице присутствует два вычисляемых столбца. Один получит тип данных VARCHAR(30), поскольку отыскиваемый при использовании оператора SELECT столбец из справочной таблицы (краткое название страны) имеет тип данных VARCHAR(30), другой вычисляемый столбец, отыскиваемый также в таблице стран, получает тип данных VARCHAR(60). Обратите внимание, что оператор SELECT заключен в двойную пару круглых скобок. Во всех синтаксических конструкциях, где присутствует одиночный оператор SELECT (оператор, возвращающий ровно одно значение одного столбца или пустое значение NULL), этот оператор должен быть заключен в круглые скобки. Внешняя пара скобок требуется, потому что выражение для любого вычисляемого столбца по правилам синтаксиса также должно заключаться в круглые скобки.

В обоих операторах SELECT в предложениях WHERE именам столбцов предшествует имя соответствующей таблицы и точка. Это так называемые уточненные имена. Имя таблицы здесь требуется, чтобы устранить возникающую неопределенность, поскольку столбец с именем CODCOUNTRY присутствует в обеих таблицах — и в FIRM, и в COUNTRY. Для уточненных имен возможно использование и псевдонимов (или алиасов, alias) таблиц. Использование псевдонимов может несколько сократить количество символов, набираемых для выполнения оператора, однако их применение имеет больший смысл, когда в сложном запросе одна и та же таблица встречается в нескольких различных конструкциях оператора SELECT. Если для таблицы задан псевдоним, то во всех уточненных именах столбцов можно использовать только псевдонимы, использование имени таблицы в этом случае недопустимо. При отсутствии псевдонима используется имя таблицы. Для главной таблицы, таблицы самого верхнего уровня, используемой в первом операторе SELECT, уточняющее имя можно не указывать.

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

FULLCOUNTRYNAME COMPUTED BY ((SELECT FULLNAME
                              FROM COUNTRY C
                              WHERE C.CODCOUNTRY = FIRM.CODCOUNTRY))

Здесь для таблицы COUNTRY задается псевдоним C. После этого в любом предложении данного оператора обращаться к данной таблице можно только по псевдониму, а не по имени таблицы.

Поскольку таблица COUNTRY является главной таблицей в операторе SELECT, то ее имя или псевдоним можно в операторе не указывать. Последнее определение вычисляемого столбца без каких-либо ошибок можно записать и в следующем виде:

FULLCOUNTRYNAME COMPUTED BY ((SELECT FULLNAME
                              FROM COUNTRY
                              WHERE CODCOUNTRY = FIRM.CODCOUNTRY))

Для таблицы же FIRM псевдоним или имя таблицы (в данном случае, именно имя этой таблицы) обязательно должно быть указано.

Подробнее о связи псевдонимов и имен таблиц см. в разделе 12.1.

Предупреждение

Для того чтобы иметь возможность просматривать все данные из приведенной в предыдущем примере таблицы FIRM пользователь, соединенный с базой данных, должен иметь привилегии просмотра не только к этой таблице, но и к справочной таблице COUNTRY. Если же производится выборка из таблицы (таблиц), получаемых при обращении к хранимой процедуре выбора, то пользователь должен иметь соответствующие полномочия к этой хранимой процедуре. Однако если пользователь выполняет оператор SELECT, который выбирает данные только из таблицы FIRM, а в заданном списке выбора отсутствуют столбцы COUNTRYNAME и FULLCOUNTRYNAME из таблицы стран, то пользователю нет необходимости иметь полномочия к таблице COUNTRY.

Использование возможностей оператора SELECT см. в разделе 12.1. Описание полномочий пользователя к таблицам, процедурам, триггерам и представлениям см. в документе «Руководство администратора».

Столбцы идентификации

Столбцы идентификации могут быть определены с помощью предложения GENERATED BY DEFAULT AS IDENTITY, либо предложения GENERATED ALWAYS AS IDENTITY. Столбец идентификации представляет собой столбец, связанный с внутренним генератором последовательностей.

Если столбец идентификации задан как GENERATED BY DEFAULT, то его значение будет увеличиваться и использовано как значение по умолчанию при каждой вставке, только в том случае, если значение этого столбца не задано явно.

Чтобы использовать сгенерированное по умолчанию значение, необходимо либо указать ключевое слово DEFAULT при вставке в столбец идентификации, или просто не упоминать столбец идентификации в списке столбцов для вставки. В противном случае будет использовано указанное вами значение.

Если столбец идентификации задан как GENERATED ALWAYS, то его значение будет увеличиваться при каждой вставке. При попытке явно присвоить значение столбца идентификации в операторе INSERT, будет выдано сообщение об ошибке. В операторе INSERT вы можете указать ключевое слово DEFAULT вместо значения для столбца идентификации.

create table greetings (id INT GENERATED ALWAYS AS IDENTITY, name CHAR(50));
INSERT INTO greetings VALUES (DEFAULT, 'hello');
INSERT INTO greetings(name) VALUES ('bonjour');
INSERT INTO greetings(id, name) VALUES (10, 'hello');         -- Запрещено

Необязательное предложение START WITH позволяет указать начальное значение отличное от нуля. Предложение INCREMENT [BY] устанавливает значение приращения. Значение приращения должно быть отлично от 0. По умолчанию значение приращения равно 1.

Идентификационные столбцы неявно являются NOT NULL столбцами.

Тип данных столбца идентификации должен быть целым числом с нулевым масштабом. Допустимыми типами являются SMALLINT, INTEGER, BIGINT, NUMERIC(x,0) и DECIMAL(x,0).

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

Идентификационный столбец не может быть изменён в обычный столбец. И наоборот.

Привилегии выполнения

Необязательное предложение SQL SECURITY {DEFINER | INVOKER} определяет, в контексте какого пользователя будут вычисляться вычисляемые столбцы. Ключевое слово INVOKER (значение по умолчанию) указывает, что вычисляемые столбцы вычисляются с правами текущего пользователя. Задание ключевого слова DEFINER означает, что вычисляемые столбцы вычисляются с правами к объектам базы данных владельца (создателя) таблицы.

Значение по умолчанию на уровне всей базы данных можно изменить оператором ALTER DATABASE SET DEFAULT SQL SECURITY.

10.2. Изменение таблиц

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

Для изменения структуры существующих таблиц используется оператор ALTER TABLE.

Листинг 10.5 Синтаксис оператора изменения таблицы ALTER TABLE

ALTER TABLE <имя таблицы> <операция изменения> [, <операция изменения>...];

<операция изменения> ::= {
     ADD <определение столбца>
   | ADD <ограничение таблицы>
   | DROP <имя столбца>
   | DROP CONSTRAINT <ограничение столбца или таблицы>
   | ALTER [COLUMN] <имя столбца> <модификация столбца>
   | ALTER SQL SECURITY {DEFINER|INVOKER}
   | DROP SQL SECURITY
   | {ENABLE | DISABLE} PUBLICATION
   | SET TABLESPACE [TO] {<имя табличного пространства> | PRIMARY}
}

<определение столбца> ::= <опр-е обычного столбца>
                        | <опр-е вычисляемого столбца>
                        | <опр-е идентификационного столбца>

<определение обычного столбца> ::=
             <имя столбца> { <тип данных> | <имя домена>}
             [DEFAULT {<литерал> | NULL | <контекстная переменная>}]
             [NOT NULL]
             [<ограничение столбца>]
             [COLLATE <порядок сортировки>]

<определение вычисляемого столбца> ::=
             <имя столбца> [<тип данных>]
            {COMPUTED [BY] | GENERATED ALWAYS AS} (<выражение>)

<определение идентификационного столбца> ::=
       <имя столбца> [<тип данных>]
      {ALWAYS|GENERATED BY} DEFAULT AS IDENTITY [(START WITH <начальное значение>)]
      [<ограничение столбца>]

<модификация столбца> ::= TO <новое имя столбца>
                        | POSITION <новая позиция>
                        | <мод-я обычного столбца>
                        | <мод-я вычисляемого столбца>
                        | <мод-я идентификационного столбца>

<модификация обычного столбца> ::=
             TYPE { <тип данных> | <имя домена> }
           | SET DEFAULT { <литерал> | NULL | <контекстная переменная>}
           | DROP DEFAULT
           | SET NOT NULL
           | DROP NOT NULL

<модификация вычисляемого столбца> ::=
   [TYPE <тип данных>] {GENERATED ALWAYS AS | COMPUTED [BY]} (<выражение>)

<модификация идентификационного столбца> ::=
             <опции автоинкремента>
           | SET GENERATED {ALWAYS|BY DEFAULT} [ <опции автоинкремента> ...]
           | DROP IDENTITY

<опции автоинкремента> ::= RESTART [ WITH <стартовое значение> ]
                         | SET INCREMENT [BY] <приращение>

<ограничение столбца> ::=
   [CONSTRAINT <имя ограничения>]
   { UNIQUE [<предложение USING>] [[IN] TABLESPACE {<имя табл. пространства>|PRIMARY}]
   | PRIMARY KEY [<предложение USING>] [[IN] TABLESPACE {<имя табл. прос-ва>|PRIMARY}]
   | REFERENCES <имя таблицы> [(<имя столбца>)]
         [ON DELETE { NO ACTION | CASCADE | SET DEFAULT | SET NULL }]
         [ON UPDATE { NO ACTION | CASCADE | SET DEFAULT | SET NULL }]
         [<предложение USING>] [[IN] TABLESPACE { <имя табл. пространства> | PRIMARY}]
   | CHECK (<условие столбца>)
   }

<ограничение таблицы> ::=
   [CONSTRAINT <имя ограничения>]
   { UNIQUE (<столбец> [, <столбец>...]) [<предложение USING>]
       [[IN] TABLESPACE { <имя табличного пространства> | PRIMARY}]
   | PRIMARY KEY (<столбец> [, <столбец>...]) [<предложение USING>]
       [[IN] TABLESPACE { <имя табличного пространства> | PRIMARY}]
   | FOREIGN KEY (<столбец> [, <столбец>...])
   | REFERENCES <имя таблицы> [(<столбец> [, <столбец>...])]
       [ON DELETE { NO ACTION | CASCADE | SET DEFAULT | SET NULL }]
       [ON UPDATE { NO ACTION | CASCADE | SET DEFAULT | SET NULL }]
       [<предложение USING>] [[IN] TABLESPACE { <имя табл. пространства> | PRIMARY}]
   | CHECK (<условие столбца>)
   }

<предложение USING> ::= USING [ASC[ENDING] | DESC[ENDING]] INDEX <имя индекса>

Примечание

Изменять таблицу может ее владелец, администратор и пользователь с ролью ALTER ANY TABLE.

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

Некоторые изменения структуры таблицы увеличивают счётчик форматов, закреплённый за каждой таблицей. Количество форматов для каждой таблицы ограничено значением 255 или 32000 для каждого представления. После того, как счётчик форматов достигнет этого значения, вы не сможете больше менять структуру таблицы или представления без сброса счётчика.

Для сброса счётчика форматов необходимо сделать резервное копирование и восстановление базы данных.

Добавление нового столбца

Для добавления нового столбца в существующую в базе данных таблицу следует ввести в операторе

ALTER TABLE следующую конструкцию:

ADD <определение столбца>

В определении добавляемого столбца присутствует как описание характеристик столбца, так и возможное ограничение столбца. В операторе можно задать значение по умолчанию для столбца (предложение DEFAULT), задать ограничение недопустимости пустого значения NOT NULL, добавить различные ограничения столбца или установить порядок сортировки (предложение COLLATE).

Синтаксис определения столбца полностью совпадают с синтаксисом, описанным в операторе CREATE TABLE.

Если в таблице, куда добавляется новый столбец, уже существуют строки c данными, то к каждой строке присоединяется новый столбец с пустым значением NULL. На это не влияет наличие в описании добавляемого столбца предложения DEFAULT.

Добавление столбца с ограничением NOT NULL без значения DEFAULT будет неудачным, если в таблице есть строки с данными. При добавлении столбца с ограничением NOT NULL рекомендуется либо установить для него значение по умолчанию, либо создать его как ненулевой, обновить значения столбца в существующих строках, а затем добавить ограничение NOT NULL.

Когда добавляется новое условие CHECK, существующие данные не проверяются на соответствие. Рекомендуется предварительно проверить существующие данные на соответствие новому условию CHECK.

Добавление столбца идентификации поддерживается, но оно будет успешным только в том случае, если таблица пуста. Добавление столбца идентификации будет неудачным, если в таблице есть хотя бы одна строка.

При каждом добавлении нового столбца номер формата увеличивается на единицу.

Добавление ограничения таблицы

Для добавления нового ограничения таблицы нужно в операторе ALTER TABLE использовать следующее предложение:

ADD <ограничение таблицы>

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

Синтаксис добавления ограничения таблицы полностью совпадают с синтаксисом, описанным в операторе CREATE TABLE.

Добавление нового ограничения таблицы не влечёт за собой увеличение номера формата.

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

Пример 1. Пусть существует таблица COUNTRY, которая содержит сведения о странах. Ее первичным ключом является столбец CODCOUNTRY. Таблица регионов REGION также содержит столбец CODCOUNTRY, который должен быть внешним ключом, ссылающимся на таблицу стран. Для добавления ограничения внешнего ключа в таблицу регионов после создания всех таблиц базы данных нужно ввести и выполнить оператор:

ALTER TABLE REGION
    ADD CONSTRAINT FK_REGION
       FOREIGN KEY (CODCOUNTRY)
       REFERENCES COUNTRY (CODCOUNTRY)
          ON DELETE CASCADE
          ON UPDATE CASCADE;

Примечание

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

Пример 2. Добавление проверочного ограничения и внешнего ключа (таблица JOB содержится в базе данных employee.fdb.):

ALTER TABLE JOB
    ADD CONSTRAINT CHK_SALARY CHECK (MIN_SALARY < MAX_SALARY),
    ADD FOREIGN KEY (JOB_COUNTRY)
       REFERENCES COUNTRY (CODCOUNTRY)
          ON UPDATE CASCADE
          ON DELETE SET NULL;

Предупреждение

При добавлении нового ограничения CHECK не осуществляется проверка соответствия ему ранее внесённых данных. Поэтому перед добавлением такого ограничения рекомендуем производить предварительную проверку данных в таблице.

Удаление столбца таблицы

Для удаления существующего столбца таблицы в операторе изменения таблицы надо ввести:

DROP <имя столбца>;

Операция удаления столбцов требует определенной осторожности. Прежде чем удалять столбец, нужно удалить все зависимости в базе данных, связанные с этим столбцом. Иными словами, нужно удалить все ссылки на этот столбец. Такие ссылки могут присутствовать:

  • в ограничениях столбцов или таблицы; такие ограничения могут существовать как в текущей, корректируемой, таблице, так и в любой другой существующей таблице базы данных. В первую очередь это могут быть ограничения первичного, уникального или внешнего ключа, в состав которого входит удаляемый столбец. Затем это могут быть ограничения внешних ключей в других таблицах, которые ссылаются на первичный или уникальный ключ корректируемой таблицы, если удаляемый столбец входит в состав первичного (уникального) ключа. Наконец, это могут быть ограничения CHECK данной или иных таблиц, в условиях которых присутствует удаляемый столбец;

  • в индексах, когда удаляемый столбец входит в состав каких-либо индексов базы данных, созданных пользователем для изменяемой таблицы;

  • в хранимых процедурах, функциях и триггерах, где присутствуют обращения к значениям удаляемого столбца;

  • в представлениях, где удаляемый столбец может присутствовать в списке выбора, а также в предложении ON соединяемых таблиц, определяющем условие соединения, в предложении WHERE, определяющем условие выборки, или в предложениях ORDER BY, существующих в представлениях, задающих упорядоченность результата выборки данных.

При каждом удалении столбца номер формата увеличивается на единицу.

Удаление ограничения

Чтобы удалить существующее ограничение столбца или ограничение таблицы следует в операторе изменения таблицы ввести:

DROP CONSTRAINT <имя ограничения столбца или таблицы>;

Для удобства выполнения такой операции желательно явно именовать все ограничения столбцов и таблиц базы данных при создании этих ограничений. Иначе придется просматривать записи системной таблицы RDB$RELATION_CONSTRAINTS, чтобы определить необходимое имя.

Ограничение первичного ключа или уникального ключа не могут быть удалены, если на него ссылается ограничение FOREIGN KEY в другой таблице. В этом случае, необходимо удалить ограничение FOREIGN KEY до удаления PRIMARY KEY или UNIQUE ключа, на которые оно ссылается. Другие ограничения — ограничения внешнего ключа и ограничения CHECK не имеют никаких зависимостей, делающих невозможным их удаление.

Удаление ограничения столбца или ограничения таблицы не влечёт за собой увеличение номера формата.

Изменение существующего столбца

При использовании оператора ALTER TABLE есть несколько вариантов изменения характеристик существующего столбца таблицы с помощью предложения ALTER [COLUMN]:

  • изменение имени (не изменяет номер формата);

  • изменение типа данных (увеличивает номер формата на единицу);

  • изменение позиции столбца в списке столбцов таблицы (не изменяет номер формата);

  • удаление значения по умолчанию столбца (не изменяет номер формата);

  • добавление значения по умолчанию столбца (не изменяет номер формата);

  • изменение типа и выражения для вычисляемого столбца (не изменяет номер формата);

  • изменение столбцов идентификации;

  • добавление ограничения NOT NULL (не изменяет номера формата);

  • удаление ограничения NOT NULL (не изменяет номера формата);

  • изменение типа идентификационного столбца или переопределение его в обычный;

  • перезапуск идентификационного столбца;

  • изменение приращения идентификационного столбца.

Изменение имени

Для изменения имени столбца в операторе изменения таблицы ALTER TABLE используется конструкция:

ALTER [COLUMN] <имя столбца> TO <новое имя столбца>

Ключевое слово TO переименовывает существующий столбец. Новое имя столбца должно быть уникальным в рамках таблицы.

Невозможно изменение имени столбца, если этот столбец включен в какое-либо ограничение - первичный или уникальный ключ, внешний ключ, ограничение столбца или ограничение таблицы CHECK.

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

ALTER TABLE STOCK
ALTER COLUMN MODELNAME TO NAME;

Изменение типа данных столбца

Для изменения типа данных столбца используется следующая синтаксическая конструкция в операторе изменения таблицы ALTER TABLE:

ALTER [COLUMN] <имя столбца> TYPE <новый тип данных>

Ключевое слово TYPE изменяет тип данных существующего столбца на другой, допустимый тип. Изменение типа, которое может привести к потере данных, не допускается. Например, количество символов в новом типе для столбца CHAR или VARCHAR не может быть меньше, чем в исходном типе.

Если столбец был объявлен как массив, то изменить ни его тип, ни размерность нельзя.

Тип BLOB можно изменить только на BLOB такого же подтипа.

Нельзя изменить тип данных столбца, который задействован в ограничениях FOREIGN KEY, PRIMARY KEY и UNIQUE.

ALTER TABLE STOCK
ALTER COLUMN ITEMID TYPE BIGINT;

Изменение позиции столбца

Для изменения позиции столбца в таблице используется следующая конструкция в операторе изменения таблицы:

ALTER [COLUMN] <имя столбца> POSITION <номер позиции>

Это самая простая операция по изменению таблицы, почти не приводящая к неприятным последствиям. Ошибки могут возникнуть лишь в том случае, если существуют операторы INSERT, в которых явно не указан список имен добавляемых столбцов. При изменении позиции столбца такие операторы станут работать неправильно и могут вызвать исключения базы данных. Это также может привести к неверному выполнению оператора SELECT, если в списке выбора был указан выбор всех столбцов таблицы (символ *), а в предложении ORDER BY был задан номер столбца, по которому выполняется упорядочивание полученных данных.

Нумерация позиций столбцов начинается с 1. Если указана позиция меньше 1, будет возвращено сообщение об ошибке. Если номер указанной позиции больше, чем количество столбцов в таблице, то новая позиция будет скорректирована, чтобы соответствовать количеству столбцов.

ALTER TABLE STOCK
ALTER COLUMN ITEMID POSITION 5;

Удаление значения по умолчанию столбца

Для удаления значения по умолчанию столбца используется следующая конструкция:

ALTER [COLUMN] <имя столбца> DROP DEFAULT

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

Если удаление значения по умолчанию производится над столбцом, у которого нет значения по умолчанию, или чьё значение по умолчанию основано на домене, то это приведёт к ошибке выполнения данного оператора.

ALTER TABLE STOCK
ALTER COLUMN MODEL DROP DEFAULT;

Добавление значения по умолчанию столбца

Для добавления значения по умолчанию столбца используется конструкция:

ALTER [COLUMN] <имя столбца> SET DEFAULT <ограничение столбца>

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

ALTER TABLE STOCK
ALTER COLUMN MODEL SET DEFAULT 'RTGZ';

Добавление ограничения NOT NULL

Предложение SET NOT NULL добавляет ограничение NOT NULL для столбца таблицы.

ALTER [COLUMN] <имя столбца>  SET NOT NULL

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

Явное ограничение NOT NULL на столбце, основанном на домене, преобладает над параметрами домена. В этом случае снятие ограничения NOT NULL с домена не распространяется на столбец таблицы.

ALTER TABLE STOCK
ALTER COLUMN ITEMID SET NOT NULL;

Удаление ограничения NOT NULL

Предложение DROP NOT NULL удаляет ограничение NOT NULL для столбца таблицы:

ALTER [COLUMN] <имя столбца>  DROP NOT NULL

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

ALTER TABLE STOCK
ALTER COLUMN ITEMID DROP NOT NULL;

Изменение вычисляемых столбцов

Тип данных и выражение, на котором основан вычисляемый столбец, можно изменить с помощью предложений COMPUTED [BY] и GENERATED ALWAYS AS:

ALTER [COLUMN] <имя столбца> [TYPE  <тип данных>]
  { GENERATED ALWAYS AS | COMPUTED [BY] } (<выражение>)

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

Изменение столбцов идентификации

Для столбцов идентификации позволено изменять способ генерации, начальное значение и значение приращения.

Изменение способа генерации столбца идентификации

Предложение SET GENERATED {ALWAYS | BY DEFAULT} позволяет изменить способ генерации столбца идентификации. Нельзя использовать этот параметр для изменения обычного столбца на столбец идентификации.

ALTER TABLE objects
ALTER ID SET GENERATED ALWAYS;

Существует два способа генерации столбца идентификации:

  • BY DEFAULT столбцы позволяют переписать сгенерированное системой значение в операторах INSERT, UPDATE OR INSERT, MERGE просто указав значение этого столбца в списке значений.

  • ALWAYS столбцы не позволяют переписать сгенерированное системой значение, при попытке переписать значение такого столбца идентификации будет выдана ошибка. Переписать значение этого столбца в операторе INSERT можно только при указании директивы OVERRIDING SYSTEM VALUE.

Изменение начального значения столбца идентификации

Предложение RESTART перезапускает последовательность, используемую для генерации значений столбца идентификации. Если указано только предложение RESTART, то последовательность сбрасывается на начальное значение, указанное при определении столбца идентификации. Если указано необязательное условие WITH, последовательность перезапускается с указанного значения.

Последующие перезапуски (без WITH) будут использовать значение START WITH, указанное при определении столбца идентификации. В настоящее время изменить начальное значение невозможно.

ALTER TABLE objects
ALTER ID RESTART WITH 100;

Изменение приращения столбца идентификации

Предложение SET INCREMENT [BY] позволяет изменить значение приращения столбца идентификации. Значение приращения должно быть отлично от 0.

ALTER TABLE objects
ALTER ID SET INCREMENT BY 2;

В одном операторе можно изменить сразу несколько свойств столбца идентификации, например:

ALTER TABLE objects
ALTER ID SET GENERATED ALWAYS RESTART SET INCREMENT BY 2;

Преобразование столбца идентификации в обычный

Предложение DROP IDENTITY удаляет связанную со столбцом идентификации системную

ALTER TABLE objects
ALTER ID DROP IDENTITY;

Изменение прав на работу с таблицей

Необязательное предложение ALTER SQL SECURITY {DEFINER|INVOKER} определяет, в контексте какого пользователя будет проходить работа с таблицей. Ключевое слово INVOKER (значение по умолчанию) указывает, что вычисляемые столбцы вычисляются с привилегиями вызывающего пользователя. Задание ключевого слова DEFINER означает, что вычисляемые столбцы вычисляются с привилегиями определяющего пользователя (владельца).

ALTER TABLE COUNTRY
ALTER SQL SECURITY DEFINER;

Если SQL SECURITY изменяется для таблицы, то триггеры, для которых явно не указано свойство SQL SECURITY, не узнают об изменении до следующей загрузки триггера в кэш метаданных. Кроме того триггеры наследуют привилегии выполнения у таблицы, если они не переопределены у самих триггеров.

Предложение DROP SQL SECURITY удаляет опцию, указанную при создании. После удаления применяется значение базы данных по умолчанию.

Значение по умолчанию на уровне всей базы данных можно изменить оператором ALTER DATABASE SET DEFAULT SQL SECURITY.

Перемещение таблицы в табличное пространство

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

ALTER TABLE <имя таблицы> SET TABLESPACE <имя табличного пространства>;

Для перемещения таблицы в основной файл базы данных примените оператор:

ALTER TABLE <имя таблицы> SET TABLESPACE TO PRIMARY

Предупреждение

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

10.3. Удаление таблиц

Для удаления существующей таблицы используется оператор DROP TABLE.

Листинг 10.6 Синтаксис оператора удаления таблицы DROP TABLE

DROP TABLE <имя таблицы>;

Примечание

Удалять таблицу может ее владелец, администратор и пользователь с привилегией DROP ANY TABLE.

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

Таблица, используемая в какой-либо активной транзакции, не будет удалена до завершения (подтверждения или отмены) этой транзакции.

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

10.4. Пересоздание таблицы

Таблица пересоздается оператором RECREATE TABLE.

Листинг 10.7 Синтаксис оператора пересоздания таблицы RECREATE TABLE

RECREATE [GLOBAL TEMPORARY] TABLE <имя таблицы>
   [EXTERNAL [FILE] '<спецификация файла>']
   (<определение столбца> [, { <определение столбца> | <ограничение таблицы>}...])
   [ON COMMIT {DELETE | PRESERVE} ROWS]
   [SQL SECURITY {DEFINER | INVOKER}];

Этот оператор создаёт или пересоздает таблицу. Если таблица с таким именем уже существует, то оператор RECREATE TABLE попытается удалить её и создать новую. Оператор RECREATE TABLE не выполнится, если существующая таблица имеет зависимости.

Данная операция доступна и для глобальных временных таблиц (GTTs) с синтаксисом, аналогичным оператору CREATE GLOBAL TEMPORARY TABLE.

Полное описание определений столбцов и ограничений таблицы смотрите в разделе CREATE TABLE.

10.5. Примечание к таблице и ее столбцам

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

Для создания примечания к таблице используется следующий синтаксис (см. листинг ):

Листинг 10.8 Синтаксис оператора создания примечания таблицы

COMMENT ON TABLE <имя таблицы> IS {'<текст>' | NULL};

Можно указать или текст примечания или задать NULL. В последнем случае будет удалено существующее примечание, если оно было ранее создано.

Например, чтобы создать примечание для таблицы PEOPLE, нужно выполнить оператор:

COMMENT ON TABLE PEOPLE IS 'Таблица, содержащая сведения о людях';

Чтобы создать примечание к столбцу уже созданной таблицы, используется следующий синтаксис:

COMMENT ON COLUMN <имя таблицы>.<столбец> IS {'<текст>' | NULL};

Например, чтобы создать примечание для столбца LAST_NAME таблицы PEOPLE, нужно выполнить:

COMMENT ON COLUMN PEOPLE.LAST_NAME IS 'Фамилия человека';