Книга: Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ
Использование INSERT для автоматических полей
Разделы на этой странице:
Использование INSERT для автоматических полей
Определение таблицы может содержать столбцы, чьи значения автоматически заполняются данными при добавлении новой строки. Это может происходить в нескольких случаях:
* столбец определен с предложением COMPUTED BY;
* столбец или домен, на котором он основан, включает предложение DEFAULT;
* для таблицы был создан триггер BEFORE INSERT для автоматического заполнения столбца.
Автоматические поля могут воздействовать на тот способ, каким вы формулируете операторы INSERT для таблицы.
Столбцы COMPUTED BY
Включение вычисляемого столбца в список входных столбцов является неверным и приводит к исключениям, как показано в следующем примере:
CREATE TABLE EMPLOYEE (
EMP_NO INTEGER NOT NULL PRIMARY KEY,
FIRST_NAME VARCHAR (15),
LAST_NAME VARCHAR(20),
BIRTH_COUNTRY VARCHAR(30) DEFAULT 'TAIWAN',
FULL_NAME COMPUTED BY FIRST_NAME || ' ' || LAST_NAME);
COMMIT;
INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, FULL_NAME)
VALUES (99, 'Jiminy', 'Cricket', 'Jiminy Cricket');
Столбцы, имеющие значение no умолчанию
Если столбец определен со значением по умолчанию, то это значение будет работать только при добавлении и только если этот столбец отсутствует в списке входных столбцов. Если немного изменить оператор добавления в предыдущем примере, то в столбец BIRTH_COUNTRY будет записано значение 'TAIWAN':
INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME)
VALUES (99, 'Jiminy', 'Cricket');
COMMIT;
SELECT * FROM EMPLOYEE WHERE EMP_NO = 99;
EMP_NO FIRST_NAME LAST_NAME BIRTH_COUNTRY FULL_NAME
99 Jiminy Cricket TAIWAN Jiminy Cricket
Значения по умолчанию никогда не заменяют значений NULL:
INSERT INTO EMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME, BI RTH_COUNTRY)
VALUES (100, 'Maria', 'Callas', NULL);
COMMIT;
SELECT * FROM EMPLOYEE WHERE EMP_NO = 100;
EMP_NO FIRST_NAME LAST_NAME BIRTH_COUNTRY FULL_NAME
100 Maria Callas Maria Callas
Если вы разрабатываете приложения с использованием компонентов, которые генерируют операторы INSERT из спецификаций столбцов операторов SELECT для наборов данных - например, Delphi или JBuilder - учитывайте такое поведение, Если ваш компонент не поддерживает метод получения значений по умолчанию с сервера, может оказаться необходимым изменить оператор, записывающий данные.
Триггеры BEFORE INSERT
При добавлении данных в таблицу, для которой существуют триггеры, автоматически заполняющие некоторые столбцы, убедитесь, что вы не задали эти столбцы в вашем входном списке, если вы хотите, чтобы триггер выполнил свою работу.
Это вовсе не означает, что вы всегда должны опускать поля, обрабатываемые триггером, во входном списке. Очень рекомендуется для поддержания целостности данных создавать триггеры, которые присваивают значения столбцам в случае, когда такие значения не задаются в операторе INSERT - особенно когда используется множество приложений и инструментов для доступа к вашей базе данных. Триггер должен проверять входное значение (например, NULL) и выполнять свои действия в соответствии с условиями.
В следующем примере первичный ключ OID заполняется в триггере:
CREATE TABLE AIRCRAFT (
OID INTEGER NOT NULL,
REGISTRATION VARCHAR(8) NOT NULL,
CONSTRAINT PK_AIRCRAFT
PRIMARY KEY (OID));
COMMIT;
/**/
SET TERM ^;
CREATE TRIGGER BI_AIRCRAFT FOR AIRCRAFT
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
IF (NEW.OID IS NULL) THEN
NEW.OID = GEN_ID(ANYGEH, 1) ;
END ^
SET TERM ;^
COMMIT;
/* */
INSERT INTO AIRCRAFT (REGISTRATION)
SELECT FIRST 3 SKIP 2 REGISTRATION FROM AIRCRAFT_OLD
ORDER BY REGISTRATION;
COMMIT;
В этом случае триггер получает значение генератора для первичного ключа, потому что ему не было передано значение во входном списке. При этом, поскольку триггер выполнит свою работу только в том случае, если обнаружит NULL, следующий оператор INSERT также будет прекрасно работать - конечно, при условии, что предоставляемое значение OID не нарушает ограничения уникальности для первичного ключа:
INSERT IN AIRCRAFT (OID, REGISTRATION)
VALUES(1033, 'ECHIDNA');
Когда вам нужно это делать? В Firebird удивительно часто. При реализации структур главная-подчиненная вы можете получить значение первичного ключа для главной строки из генератора до того, как строка будет отправлена в базу данных, простым вызовом DSQL:
SELECT GEN_ID(YOURGENERATOR, 1) FROM RDB$DATABASE;
Генераторы работают вне управления транзакций, и если вы получили номер, то он ваш. Вы можете использовать его для столбцов внешнего ключа подчиненных строк в клиентских буферах, если вы их создали, без сохранения главной строки в базе данных. Если пользователь решил отменить действия, то ничего не нужно "аннулировать" на сервере. Если вы когда-либо старались добиться подобной возможности в СУБД, которая использует автоинкрементный или "идентифицирующий" тип, вы полюбите такую возможность.
Другие аспекты этой техники см. в главе 31.
- Восстановление с использованием инструмента gbak
- Типы страниц и их использование
- Использование констант
- Инструкция INSERT INTO ... FROM ... UNION ...
- Использование переменной окружения ISC_PATH
- Использование сервера Yaffil внутри процесса
- Использование CAST() с типами дата
- Использование типов содержимого и столбцов
- Вызов хранимых процедур InterBase с использованием стандартного синтаксиса ODBC
- Использование кнопки Автосумма
- 24.7. Использование программы-твикера
- Использование отдельных процессоров XSLT