Содержание
transfer table
Версии сервера
2.5 | 3.0 |
---|---|
- | - |
Доступно в
Формат
Передача части таблицы от одного сервера другому.
Суть проблемы.
Есть центральная база данных и большое количество филиалов. Необходимо создать репликацию одной или нескольких таблиц с центральной БД. Эта проблема может быть решена применением EXECUTE STATEMENT. Однако за период накопления, в филиалах набирается большой объем данных. Передача их открытым трафиком приводит к серьезной загрузке канала, да и непрогнозируемым нагрузкам на центральный сервер БД. Более разумно сжимать передаваемый трафик архиватором, а обрабатывать посылки данных по расписанию. Для реализации такого обмена, данные из таблицы-источника сохраняются во внешней (EXTERNAL) таблице, которая находится в отдельном файле, который после формирования архивируется и передается в сжатом виде. Собственно, настоящая статья описывает процедуру формирования пакета для передачи.
Описание
Процедура принимает следующие входные данные
1. имя передаваемой таблицы
2. условия отбора (секция WHERE запроса). В случае пустого значения этого параметра вся таблица передается полностью
3. путь и имя/расширение создаваемого файла
По окончании процедуры по указанному пути создается файл, содержащий запрошенные данные, и готовый к передачи другому серверу.
ВНИМАНИЕ! Для работы этой процедуры использована функция создания внешних (EXTERNAL) таблиц. По умолчанию эта возможность отключена в фале настроек firebird.conf Для работы этой процедуры параметру ExternalFileAccess необходимо установить значение Full
ВНИМАНИЕ! для передачи данных создается внешняя (EXTERNAL) таблица на которую накладываются ограничения связанные с таким объектом. В частности невозможна передача объектов типа BLOB. Подробности см. в соответствующей статье CREATE TABLE
Часть кода взята из статьи RDB$FIELDS
Пример
CREATE OR ALTER PROCEDURE TRANSFER ( TABLE_NAME VARCHAR(1000), where_str VARCHAR(1000), path_file VARCHAR(1000) = 'c:\transfer.db') AS DECLARE variable temp_s1 VARCHAR(10000); DECLARE variable i INTEGER; DECLARE variable res VARCHAR(10000); BEGIN res = 'CREATE TABLE ' || TABLE_NAME ||'_REP EXTERNAL ' || ASCII_CHAR(39) || PATH_FILE || ASCII_CHAR(39) || ' ('; SELECT COUNT(*) FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = :TABLE_NAME || '_REP' INTO i; IF (i > 0 ) THEN BEGIN EXECUTE STATEMENT 'DROP TABLE ' || TABLE_NAME || '_REP' WITH AUTONOMOUS TRANSACTION; END i = 0; FOR SELECT TRIM(RDB$RELATION_FIELDS.RDB$FIELD_NAME) ||' '|| TRIM( ( SELECT CAST( CASE T2.RDB$FIELD_TYPE WHEN 7 THEN 'SMALLINT' WHEN 8 THEN 'INTEGER' WHEN 12 THEN 'DATE' WHEN 13 THEN 'TIME' WHEN 14 THEN 'CHAR('||T2.rdb$field_length||')' WHEN 16 THEN iif(T2.rdb$field_sub_type = 0,'BIGINT', 'NUMERIC('||T2.RDB$FIELD_PRECISION||','||(-1*T2.rdb$field_scale)||')') WHEN 35 THEN 'TIMESTAMP' WHEN 37 THEN 'VARCHAR('||T2.rdb$field_length||')' WHEN 261 THEN 'BLOB SUB_TYPE '||T2.rdb$field_sub_type||' SEGMENT SIZE '||T2.rdb$segment_length ELSE CAST(T2.RDB$FIELD_TYPE AS VARCHAR(10)) END ||iif(T2.RDB$NULL_FLAG = 1,' NOT NULL ',' ') ||COALESCE(' '||RDB$DEFAULT_SOURCE,'') ||COALESCE(' '||rdb$validation_SOURCE,'') AS VARCHAR(1000)) FROM RDB$FIELDS T2 WHERE T2.RDB$FIELD_NAME = RDB$RELATION_FIELDS.RDB$FIELD_SOURCE ) ) AS SPECIFICATION FROM RDB$RELATION_FIELDS INNER JOIN RDB$FIELDS ON (RDB$FIELDS.RDB$FIELD_NAME = RDB$RELATION_FIELDS.RDB$FIELD_SOURCE), RDB$TYPES WHERE RDB$TYPES.RDB$TYPE = RDB$FIELDS.RDB$FIELD_TYPE AND RDB$TYPES.RDB$FIELD_NAME = 'RDB$FIELD_TYPE' AND RDB$RELATION_NAME = :TABLE_NAME ORDER BY RDB$FIELD_POSITION INTO TEMP_S1 do BEGIN res = res || CASE WHEN i > 0 THEN ', ' ELSE '' END || TEMP_S1; i = i + 1; END res = res || ');'; EXECUTE STATEMENT res WITH AUTONOMOUS TRANSACTION; temp_s1 = 'INSERT INTO ' || TABLE_NAME || '_REP SELECT ' || TABLE_NAME || '.* FROM ' || TABLE_NAME || CASE WHEN CHAR_LENGTH(WHERE_STR) < 2 THEN ' ;' ELSE ' where ' || WHERE_STR || ' ;' END; EXECUTE STATEMENT temp_s1 WITH AUTONOMOUS TRANSACTION; EXECUTE STATEMENT 'DROP TABLE ' || TABLE_NAME || '_REP' WITH AUTONOMOUS TRANSACTION; END
См. также
Источник
%Firebird%\doc\565
Обсуждение