Nikolay Trifonov пишет:
> Сорри, но начну новый пост, ОЕ заглючил.
>
> один вопрос у меня в голове не укладывается: есть таблица CHANGES, в которой 
> для репликации записываются в какой строчке что изменилось триггером:
>


Сразу извиняюсь за размер поста, но
коротко тут не скажешь...
вопрос репликации достаточно сложный
сам по себе, да еще индивидуальные
особенности БД + конторы накладывают
ограничения. Поделюсь своим решением,
которое IMHO не панацея, но работает:
Имеем:
а) 32 филиала (автоматизированная точка
розничной продажи). Кратко назовем
"ПОФ"
б) 1 центральный офис для
автоматизированных филиалов. Кратко
назовем "ПОЦО"
в) система которая связана с закупкой
товара у поставщиков (прием заявок  от
филиалов, их обработка, отправка
поставщикам). "Первичные" справочники,
от которых все "пляшут" - именно тут.
Кратко назовем "ПОГИД"

Системы ПОФ и ПОЦО написаны мною,
соответственно могу делать с ними все,
что хочу. Система ПОГИД работает в
конторе давно, исходников нет, так что
модификации допускаются на уровне БД.

Нужна была система с "общими
синхронизированными" справочниками и
"чтобы в ПОЦО были все документы из
ПОФ". В ПОФ ДОПУСКАЕТСЯ заведение новых
записей в справочники!

Долго думал, в итоге получилась такая
конфигурация ПО (только то, что
касается репликации):
1) ПОФ и ПОЦО используют один и тот же
исполняемый файл (что значительно
облегчило мою работу) и отличаются
нюансами "реализации" БД (несколько
иной набор "служебных" таблиц,
триггеров и ХП).

а) Реализован встроенный механизм
импорта справочников из ПОГИД, в
котором готовятся 9 файлов со
справочниками: товары, контрагенты и
т.д.  В справочниках ПОФ и ПОЦО
используется простой PK с заполнением
по генератору, во всех справочниках
есть поле "ссылка_на_погид" в котором
должно храниться значение PK из ПОГИД.
Когда импортируется запись в
справочник ПОФ или ПОЦО - проверяется
наличие такого значения в
"ссылка_на_погид", если оно есть - то update,
если нет - то insert. Когда запись
заноситься юзером, то поле
"ссылка_на_погид" is null.
Когда формируется пакет данных из ПОФ
для ПОЦО то из справочников ПОФ
выбираются записи у которых
"ссылка_на_погид" is null, которые потом
импортируются (через "таблицу
перекодировок": "код
филиала"-"PK_в_филиале" - "PK_в_ЦО"...) в БД
ПОЦО. Это упрощенно, так как на самом
деле проверяется наличие "такой"
записи, если она есть - то импорта не
происходит - проставляется код
существующей записи.
В ПОЦО работает еще одна программа,
которая смотрит БД ПОЦО на наличие is null
и позволяет указать код
соответствующего PK из  ПОГИД. В
результате в филиал отправляется файл,
который содержит информацию "код
филиала"-"PK_в_филиале" - "PK_в_ПОГИД"  -
"таблица", когда он импортируется, то в
соответствующей записи поле
"ссылка_на_погид" становится равна
"PK_в_ПОГИД" и она перестанет
передаваться в ПОЦО. При следующем
импорте справочников в ПОФ - данная
строка будет обновлена полностью. Плюс
в БД ПОФ реализован механизм "перехода
на PK с наибольшим  значением для общего
"ссылка_на_погид"". Допустим есть две
строки в справочнике:
pk - "ссылка_на_погид"
1    100
2    100
это не очень красиво, поэтому при
проставлении значения в поле
"ссылка_на_погид" проверяется наличие
записей с таким же значением и с
помощью триггера происходит перенос
данных на новый код, например вот так:
AS
declare variable tmp_analog_id integer;
begin
    if (new.parent_id is not null) then
        begin
            for
            select an.analog_id
            from analog an
            where an.parent_id = NEW.PARENT_ID
            and an.analog_id <> NEW.analog_id
            into :tmp_analog_id
            do begin
                update defectureitem di set di.analog_id =
NEW.analog_id WHERE di.analog_id = :tmp_analog_id;
                update sprice sp set sp.analog_id = NEW.analog_id WHERE
sp.analog_id = :tmp_analog_id;
                update goods gd set gd.analog_id = NEW.analog_id WHERE
gd.analog_id = :tmp_analog_id;
                delete from analog an where an.analog_id =
:tmp_analog_id;
            end
        end
end
/*конец триггера*/
в итоге имеем "красивые и
синхронизированные" справочники,
причем никто не ограничивает из
заполнение в ПОФ. Для этого нужно:
процедура импорта справочников из
ПОГИД, выгрузка "заведенных" в ПОФ
записей в ПОЦО, импорт в ПОФ ссылок из
ПОЦО.

б) теперь касаемо документов и
связанных с ними таблиц. Все документы,
которые влияют на товарный запас имеют
набор триггеров, которые фиксируют в
"таблицах состояния" необходимость
передачи этого документа в ПОЦО.
Например вот так:
AS
begin
    /*добавление документа в список
синхронизируемых*/
    UPDATE sync$move sm SET sm.time_send = null, sm.time_recv = null
    WHERE sm.pr_key = NEW.move_id;
    IF (row_count = 0) THEN
        BEGIN
            INSERT INTO sync$move (pr_key) VALUES(NEW.move_id);
        END
end

AS
begin
    /*удаление документа из списка
синхронизируемых*/
    DELETE FROM sync$move sm WHERE sm.pr_key = OLD.move_id;
    /*добавление документа в список
удаляемых*/
    DELETE FROM sync$deleted sd WHERE sd.table_name = 'MOVE' AND
sd.pr_key = OLD.MOVE_ID;
    INSERT INTO sync$deleted (table_name,pr_key)
VALUES('MOVE',OLD.move_id);
end

при формирование пакета данных из ПОФ
в ПОЦО выбираются данные у которых  WHERE
NOT EXISTS (SELECT sm.pr_key
               FROM sync$move sm
               WHERE sm.pr_key = mo.move_id
               AND sm.time_send IS NOT NULL
               AND sm.time_recv IS NOT NULL)
когда этот пакет (содержит 9 файлов)
приходит в ПОЦО, то робот пытается его
загрузить. По окончании импорта
формируется пакет "квитанций" (1 файл),
при обработке которого в ПОФ
UPDATE sync$move sm SET sm.time_recv = :time_recv WHERE sm.pr_key =
:pr_key;
И этот документ больше не выгружается
из ПОФ в ПОЦО (до тех пор пока его кто
нибудь не "тронет").
Итого: для синхронизации документов
(из ПОФ в ПОЦО) нужно подготовить пакет
в ПОФе (9 файлов), обработать его в ПОЦО
и вернуть квитанцию (1 файл). В БД ПОЦО
не используется "составных" PK
(филиал+PK_в_филиале), а  используется
"таблицы перекодировок". Это позволило
не менять исполняемый файл, оставить
всю логику неизменной. Для этого
поступил так: в каждом ПОФ есть
несколько отделов (складов), при
переносе документов в БД ПОЦО не
происходит "кучкование" документов на 1
"синтетический" отдел, соответствующий
этому ПОФу, а каждый отдел ПОФа
является полноценным отделом в ПОЦО.


2) Для передачи данных используется dbf
пожатый zip, канал передачи ftp (off-line).
3) Для обработки данных от ПОФ написан
сервис, который по таймеру ищет на
фтп-сервере данные от ПОФ и
импортирует их в БД ПОЦО. По
результатам импорта, в ПОФ
отправляется файл, в котором указаны PK
УСПЕШНО обработанных записей. Пока
такого подтверждения не получено -
филиал будет слать эту запись в ПОЦО.

Это если коротко. Если нужна
"конкретика" - спрашивай...


Рубан Станислав

Ответить