Загрузка с помощью View и триггера
Подумаем над решением для первого вопроса:
- Как обеспечить вызов процедуры для каждой записи из временной таблицы SALES?
Существует ли в РЕД Базе Данных способ загрузить в таблицу все записи из выборки (из другой таблицы, представления и т.п) одной командой SQL?
Как вариант, это можно было бы сделать так:
INSERT into TARGET(col1,col2, ...) SELECT FLD1, FDL2, ... FROM SALES;
Средства SQL JSON (например, JSON TABLE) позволяют разобрать синтаксис JSON записей из таблицы SALES в рамках одного оператора SELECT. Но в нашем случае INSERT нужно делать не в одну, а сразу в 3 связанные таблицы, да так, чтобы гарантировано обеспечить целостность данных. С другой стороны, у нас есть процедура, которая делает то, что требуется, но INSERT в процедуру синтаксис стандартного SQL не предусматривает.
Все же, стандартный SQL предоставляет способ обойти эту проблему. Это триггеры!
Триггер является программой, которая хранится в области метаданных базы данных и выполняется на стороне сервера. Он вызывается автоматически при наступлении одного или нескольких событий, относящихся к одной конкретной таблице (к представлению), или при наступлении одного из событий базы данных.
- В триггере можно вызывать хранимую процедуру и передавать ей значения параметров на базе старых или новых значений полей записей этой таблицы или представления.
- Табличные триггеры выполняются в контексте той транзакции, в контексте которой выполнялся запрос или программа, вызвавшие соответствующее событие.
Следовательно, нужно создать специализированное представление и триггер на событие вставки в него, в котором вызвать процедуру разбора входной JSON-строки.
Создадим такое представление и назовем его INPUT_PARSER:
/* INPUT_PARSER */
CREATE OR ALTER VIEW INPUT_PARSER (INSTRING)
AS
select first 1 coalesce(jvar,jsrc) instring from SALES
;
В этом представлении предусмотрено единственное поле INSTRING, в которое будем помещать входную запись.
В данном варианте представления внутренний select возвращает первое ненулевое значение из поля JVAR или JSRC из таблицы SALES.
Нам потребуется единственный триггер, который будет назначен на все события BEFORE INSERT OR UPDATE OR DELETE. Однако, запускать процедуру он будет только при наступлении события BEFORE INSERT, а на остальные — просто ничего не делать. В процедуру передается вставляемое значение из поля INSTRING, которое содержит данные об одной продаже в формате JSON.
/* INSERT_PARSER */
CREATE OR ALTER TRIGGER INSERT_PARSER FOR INPUT_PARSER
ACTIVE BEFORE INSERT OR UPDATE OR DELETE POSITION 0
AS BEGIN
if (INSERTING) then
begin
execute procedure IMPORT_SALE_JSON(NEW.INSTRING);
end
END;
Теперь, разбор и загрузка целиком всей очередной порции будет запускаться одним оператором SQL:
INSERT INTO INPUT_PARSER (INSTRING)
SELECT CAST(JSRC AS VARCHAR(3000)) FROM SALES
Что получилось в результате:
-
Благодаря применению представления и триггера удалось избежать медленного цикла перебора для каждой входящей записи из таблицы SALES. Все содержимое таблицы SALES загружается сразу в три таблицы базы данных одним оператором INSERT
-
Загрузка может быть выполнена в рамках единой транзакции для каждой записи или всего пакета целиком.
-
Процедура написана таким образом, что исключает повторную загрузку одних и тех же данных. Ее можно запускать несколько раз. В случае сбоя можно повторить, чтобы добавить оставшиеся записи.
-
Наличие представления INPUT_PARSER позволяет внешнему приложению-загрузчику загружать данные не в промежуточную таблицу SALES, а прямо в представление. Таблицу SALES можно удалить.
-
Загрузку можно производить не только из таблицы SALES или приложения-загрузчика, но и, например, из файлового блоба с помощью запроса типа
INSERT INTO INPUT_PARSER (INSTRING) SELECT JSON_TABLE ... READ_FILE('BLOB_DIR/JSRC2.TXT') FROM RDB$DATABASE -
Предложенное решение хорошо автоматизируется.
-
Найден вариант ответов для решения задач из остальных вопросов из предыдущей главы.
Дата последнего изменения: 11.09.2026
Если вы нашли ошибку, пожалуйста, выделите текст и нажмите Ctrl+Enter.