Опубликован: 07.05.2010 | Уровень: специалист | Доступ: платный
Лекция 20:

Генераторы и триггеры. Реализация автоинкрементного поля

< Лекция 19 || Лекция 20: 12 || Лекция 21 >
Аннотация: Эта лекция посвящена мощным инструментам клиент-серверных баз данных: генераторам и триггерам. Вы узнаете, что такое генераторы, как их создавать и как менять их значения. Так же вы изучите триггеры и события, на которые они реагируют. Кроме того, вы научитесь создавать автоинкрементные ключевые поля.

Генераторы

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

В основном, генераторы используют для создания автоинкрементных полей. Для каждого такого поля придется создавать собственный генератор. Генератор, совместно со специальным триггером, гарантирует, что значение этого поля всегда будет уникальным. Создаются генераторы с помощью оператора CREATE GENERATOR:

CREATE GENERATOR Gen1;

Внимание! Генераторы можно создавать, но удалить их не получится, поэтому в реальной базе данных прежде продумайте, какие генераторы у вас будут, а потом только создавайте их. Откройте утилиту IBConsole, войдите в локальный сервер и откройте нашу базу данных FIRST. Затем запустите Interactive SQL, и создайте генератор Gen1, как в примере выше. Затем выделите раздел "Generators" в дереве серверов, и в правой части вы увидите наш генератор, а также его текущее значение:

Раздел "Generators" базы данных

Рис. 20.1. Раздел "Generators" базы данных

Как видно из рисунка, генератору сразу присваивается значение 0. Тем не менее, во избежание возможных ошибок, вторым шагом нередко присваивают генератору это значение оператором SET GENERATOR:

SET GENERATOR Gen1 TO 0;

Выполните этот пример с помощью утилиты Interactive SQL. Таким образом, генераторам можно присваивать любое целое значение, даже отрицательное.

Иногда бывает необходимым присваивать генератору не нулевое, а другое значение. Например, если вы перенесли базу данных из Paradox в InterBase. В этом случае, таблица уже содержит записи, которые пронумерованы. Автоинкрементное поле при переносе превращается в INTEGER. Требуется посмотреть последнее значение этого поля, и присвоить генератору именно его.

Увеличение шага генератора

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

GEN_ID(Gen1, 1)

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

SELECT GEN_ID(Gen1, 1) FROM RDB$DATABASE;

В нижнем окне Interactive SQL будет выведен результат:

Результат SQL-запроса

Рис. 20.2. Результат SQL-запроса

Как видно из рисунка, мы получили значение 1. Выполните также команду COMMIT, чтобы завершить транзакцию, затем закройте Interactive SQL. Выделите раздел Generators и убедитесь, что значение изменилось. Что, собственно, произошло? Дело в том, что когда вы создаете новую базу данных, InterBase прежде всего создает в ней собственные системные таблицы. Одной из таких таблиц является RDB$DATABASE, которая всегда хранит только одну запись с некоторыми системными параметрами базы данных. Эту же таблицу иногда применяют для "пустых" запросов, которые возвращают значение одной из переменных или вычисляемое значение. Нашим предыдущим запросом мы вначале увеличили значение генератора на 1, затем вывели его на экран оператором SELECT. Узнать текущее значение генератора, не увеличивая его, можно строкой:

SELECT GEN_ID(Gen1, 0) FROM RDB$DATABASE;

где в процедуре GEN_ID() указывается шаг 0.

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

Совет: если генератор уже находится в использовании, в рабочей базе данных, НИКОГДА не переустанавливайте его значений вручную - это чревато порчей целостности и достоверности данных.

Триггеры

Триггерами называются подпрограммы, которые всегда выполняются автоматически на стороне сервера, в ответ на изменение данных в таблицах БД.

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

Триггер может выполняться в двух фазах изменения данных: до(Before) какого то события, или после(After) него. Синтаксис определения триггера следующий:

CREATE TRIGGER <имя_триггера> FOR <имя_таблицы>
[ACTIVE | INACTIVE]
{BEFORE | AFTER} {DELETE | INSERT \ UPDATE}
[POSITION <число>]
AS
[DECLARE [VARIABLE] <переменная тип_данных>;]
BEGIN
  <операторы_триггера>
END

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

[ACTIVE | INACTIVE]

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

< Лекция 19 || Лекция 20: 12 || Лекция 21 >
Евгений Медведев
Евгений Медведев

В лекции №2 вставляю модуль данных. При попытке заменить name на  fDM выдает ошибку: "The project already contains a form or module named fDM!". Что делать? 

Анна Зеленина
Анна Зеленина

При вводе типов успешно сохраняется только 1я строчка. При попытке ввести второй тип вылезает сообщение об ошибке "project mymenu.exe raised exception class EOleException with message 'Microsoft Драйвер ODBC Paradox В операции должен использоваться обновляемый запрос'. 

Денис Попов
Денис Попов
Россия, Оренбург, Оренбургский государственный университет, 2015
Рустам Кадыров
Рустам Кадыров
Россия, Тирлян, Тирлянская школа №5, 2003