Инструменты пользователя

Инструменты сайта


Боковая панель

Введение

Статьи и часто задаваемые вопросы

Установка и настройка

Обработка ошибок

Полезные запросы SQL

Тематические группы

transfer_table



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

Только авторизованные участники могут оставлять комментарии.
transfer_table.txt · Последние изменения: 2014/02/04 16:44 (внешнее изменение)