:: Архив конференции по VFP до 2005 года
Re: Организовать суммирующий файл ч/з тригера
Иван_С
Автор
Цитата:
-) Если во второй таблице модифицируется больше чем одна запись (кроме значения изменились критерии), то вся модификация обязательна должна быть окружена транзакцией - необходима проверка на уровень вложенности транзакций (не может быть больше 5)

обязательно использовать транзакции? Я вставил буферизацию типа - 5 и считал что это хорошо . Или тоже есть условия, когда лучше работать с транзакцией, а когда с буферизацией?
Ratings: 0 negative/0 positive
Re: Организовать суммирующий файл ч/з тригера
Владимир Максимов

Сообщений: 14098
Откуда: Москва
Дата регистрации: 02.09.2000
Внутри триггера менять уровень буферизации нельзя!

Дело в том, что триггер - это последний уровень контроля данных непосредственно перед их вставкой в таблицы. Получается примерно следующая логика:

  • Для модификации таблицы1 данная таблица переводится в режим буферизации
  • По окончании модификации необходимо сбросить буфер
  • Процесс сброса буфера, как правило, окружается транзакцией
  • Непосредственно в процессе сброса буфера срабатывает триггер

    Таким образом, внутри тела триггера уже есть открытая транзакция. Т.е. все то, что выполняется в теле триггера выполняется внутри конструкции BEGIN TRANSACTION. А менять режим буферизации внутри открытой транзакции невозможно. Это системное ограничение FoxPro.

    Следовательно, для отката внесенных изменений остается только транзакция - это случай когда первая модификация выполнилась успешно, а на второй произошла ошибка (например, запись заблокирована другим пользователем).

    Почему эту вложенную транзакцию (внутри тела триггера) вообще надо открывать? Ведь внешняя транзакция и так откатит все изменения. А потому, что в общем случае, мы не можем быть уверены, что транзакция была открыта вне триггера. Например, прямая модификация таблиц через BROWSE.

    Однако проверять факт того, что Таблица2 находится в режиме буферизации тем не менее необходимо. Даже если ты ее открываешь внутри тела триггера. Дело в том, что существуют настройки, позволяющие устанавливать режим буферизации "по умолчанию" у любой вновь открываемой таблицы. Это настройки нулевой рабочей области. Примерно так:

    CLOSE DATA
    SET MULTILOCK ON
    =CursorSetProp("buffering",5,0)
    USE MyTable
    ?CursorGetProp("buffering")

    Т.е. по сути, таблица открылась уже с установленной 5 буферизацией. Значит, внутри тела триггера надо предусмотреть сброс буфера той строки, которую изменили, если таблица в режиме буферизации. В данном случае речь идет о Таблице2 (с итоговыми суммами). С Таблицей1 ничего делать не надо!

    Итого, получаем примерно такой код:

    LOCAL lcOldError, llError
    lcOldError = ON("ERROR")
    ON ERROR llError = .T.
    llError = .F.
    LOCAL llTransaction
    IF TXNLEVEL()<5
    BEGIN TRANSACTION
    llTransaction = .T.
    ENDIF
    IF m.llError = .F.
    USE Таблица1
    IF m.llError = .T.
    * Ошибка открытия таблицы
    ENDIF
    ENDIF
    IF m.llError = .F.
    ...
    REPLACE ...
    IF m.llError = .T.
    * Ошибка модификации
    ENDIF
    ENDIF
    IF m.llError = .F. AND CursorGetProp("buffering","Таблица1")>1
    IF TableUpdate(.F.,.T.,"Таблица1")=.F.
    llError = .T.
    * Ошибка модификации
    ENDIF
    ENDIF
    ...
    * Завершение триггера
    IF m.llTransaction = .T.
    IF m.llError = .T.
    * Отказ триггера
    ROOLBACK
    ELSE
    END TRANSACTION
    ENDIF
    ENDIF
    * Восстановление исходных настроек
    USE IN SELECT("Таблица1")
    ON ERROR &lcOldError
    RETURN NOT m.llError

    Это опять же только приблизительная схема. Например, здесь я взял самый примитивный обработчик ошибок. При такой схеме я никокгда не пойму почему произошел отказ триггера. Нет информации. Лучше всего создать какой-нибудь триггер через Referenty Integriti и посмотреть как там организован обработчик ошибок внутри триггера. Можно напрямую использовать эту схему.




    ------------------
    Ratings: 0 negative/0 positive
  • Re: Организовать суммирующий файл ч/з тригера
    Иван_С
    Автор
    Все равно не могу понять в чем разница этих написаний внутри тригера первой таблицы:
    1.
    sele 0
    use (таблица2) again alias '_rg_sum'
    =CURSORSETPROP("Buffering" ,4,'_rg_sum')
    изменения в таблице 2


    IF !TABLEUPDATE(.T.,.t.,'_rg_sum'')
    =TABLEREVERT(.T.)
    RETURNER = .f.
    ENDIF


    2.

    sele 0
    use (таблица2) again alias '_rg_sum'
    begin transaction
    изменения в таблице 2
    end transaction

    чем отличается в работе первый и второй вариант?
    если честно я слабоват в вопросе трансакций
    Ratings: 0 negative/0 positive
    Re: Организовать суммирующий файл ч/з тригера
    Владимир Максимов

    Сообщений: 14098
    Откуда: Москва
    Дата регистрации: 02.09.2000
    А теперь попробуй в первом варианте в командном окне написать примерно такое:

    USE Таблица1
    BEGIN TRANSACTION
    REPLACE Значение WITH Значение

    И полюбуйся как тебя "обложит" FoxPro. И на какой именно команде.

    Т.е. команда REPLACE вызовет срабатывание триггера, но поскольку снаружи уже есть открытая транзакция, то внутри триггера пойдет ругань на команду =CURSORSETPROP("Buffering" ,4,'_rg_sum')

    Кроме того, буферизация в данном случае не обеспечивает главного. Модификации в нескольких записях "пакетом". Т.е. либо во всех записях будет успешная модификация, либо ни в одной. Но ни в коем случае не частичная (одна записалась, а другая нет).




    ------------------
    Ratings: 0 negative/0 positive
    Re: Организовать суммирующий файл ч/з тригера
    Igor Korolyov

    Сообщений: 34580
    Дата регистрации: 28.05.2002
    Hi, Иван_С!

    Ещё раз внимательно перечитай сообщение Владимира. И попробуй например свой
    вариант ХП со следующим примитивнейшим кодом:

    USE таблица1 SHARED
    CURSORSETPROP("таблица1", "Buffering", 5)
    REPLACE значение1 WITH значение1 + 1, ;
    значение2 WITH значение2 + 2 ;
    FOR измерение1 = "aaa"
    BEGIN TRANSACTION
    IF !TABLEUPDATE(1, .F., "таблица1")
    ROLLBACK
    ELSE
    END TRANSACTION
    ENDIF




    ------------------
    WBR, Igor
    Ratings: 0 negative/0 positive
    Re: Организовать суммирующий файл ч/з тригера
    Иван_С
    Автор
    Действительно сломалось и в результате дошел смысл сказанного ранее
    Ratings: 0 negative/0 positive


    Извините, но у вас нет прав для того, чтобы оставлять сообщения в этом форуме.

    On-line: 3 (Гостей: 3)

    © 2000-2024 Fox Club 
    Яндекс.Метрика