powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Вопрос по стабильному курсору FB 3
11 сообщений из 11, страница 1 из 1
Вопрос по стабильному курсору FB 3
    #39638336
Фотография CyberMax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В базе есть таблица с сальдо-оборотами абонентов. В ней есть триггер, который обновляет начальное сальдо следующего периода при изменении конечного сальдо (AFTER UPDATE):
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
    IF (NEW.BALANCE_FINAL <> OLD.BALANCE_FINAL) THEN
            UPDATE INF$ABONENT$BT BT
            SET
                BALANCE_INITIAL = NEW.BALANCE_FINAL
            WHERE
                (BT.ID_ABONENT = NEW.ID_ABONENT)
                AND (BT.ID_SERVICE = NEW.ID_SERVICE)
                AND (BT.ID_PERIOD = INC_PERIOD(NEW.ID_PERIOD));


В FB 2.5 все работало. В FB 3.0 же при выполнении вот такой команды начальное сальдо следующего периода не обновляется:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
    UPDATE INF$ABONENT$BT BT
    SET
        BT.BALANCE_FINAL = 100
    WHERE
        (BT.ID_ABONENT = :ID_ABONENT)
        AND (BT.ID_PERIOD >= :ID_FROM_PERIOD)
    ORDER BY
        BT.ID_PERIOD;


Если во втором условии сделать "=", то все работает - сальдо переносится.
Сделал лог изменения начального сальдо по одной услуге. Получилась вот такая картина (201804, 201805 - это значения ID_PERIOD):
1 201804: 143.85 -> 143.85
2 201805: 231.55 -> 431.55
3 201805: 431.55 -> 231.55
Если я правильно понимаю, то получается следующая последовательность:
1. В записи 201804 обновляется конечное сальдо.
2. Это вызывает обновление начального сальдо у записи 201805.
3. После этого сервер переходит к записи 201805, обновляет ее, "вспоминая", что на момент старта запроса у него было другое начальное сальдо. И тем самым возвращает все как было.

Вопросы: такое поведение так и задумывалось? если да, то как тогда делать каскадные обновления записей, когда следующее обновление записи зависит от другого?
...
Рейтинг: 0 / 0
Вопрос по стабильному курсору FB 3
    #39638337
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CyberMax,

не надо делать такие вещи в строчных триггерах (а триггеров уровня оператора у нас нет). Да и в 2.5 оно работало только по чистой случайности.
...
Рейтинг: 0 / 0
Вопрос по стабильному курсору FB 3
    #39638342
Фотография CyberMax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

Оно работало во всех версиях FB по вполне логичной причине - запись обновили, и сервер при обработке следующей записи видит измененную версию.
И все таки, как сделать каскадное обновление - есть варианты?
...
Рейтинг: 0 / 0
Вопрос по стабильному курсору FB 3
    #39638348
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CyberMax,

мне это не очевидно из приведённого кода.

CyberMaxИ все таки, как сделать каскадное обновление - есть варианты?

опять мне не ясно что у вас там за каскады и по каким критериям связи идут. В любом случае в триггерах лучше не держать код который делает изменения в той же таблице для которой этот триггер написан.
...
Рейтинг: 0 / 0
Вопрос по стабильному курсору FB 3
    #39638366
Фотография Старый плюшевый мишка
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис В любом случае в триггерах лучше не держать код который делает изменения в той же таблице для которой этот триггер написан.

Здрасьте приехали. Триггерные петли через три таблицы тоже в помойку?
...
Рейтинг: 0 / 0
Вопрос по стабильному курсору FB 3
    #39638375
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CyberMax,

сложная бизнес-логика в триггерах - зло.
Это много раз говорилось.
Зачем тут вообще сделано через триггер - я не знаю.
И это ты ещё на ограничение по глубине рекурсии не попал.
...
Рейтинг: 0 / 0
Вопрос по стабильному курсору FB 3
    #39638573
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CyberMax IF (NEW.BALANCE_FINAL <> OLD.BALANCE_FINAL) THEN
вот это в after update? ёшкин кот...
...
Рейтинг: 0 / 0
Вопрос по стабильному курсору FB 3
    #39638864
Фотография CyberMax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тогда уважаемые hvlad и kdv, объясните, как правильно реализовать следующее:
NROW STARTAMOUNTFINISH1000200030554505
Поле FINISH = START + AMOUNT.
Требуется, чтобы при изменении поля FINISH у любой строки, обновлялось поле START у последующих строк. Например, вот так:NROW STARTAMOUNTFINISH1044240434594909
Сейчас это сделано простым способом - в триггере AFTER UPDATE, если меняется поле FINISH, обновляется поле START у следующей строки, и так каскадом обновляется весь стек. В обычных случаях каскад состоит из одной-двух строк, поэтому никаких проблем с производительностью и прочим нет. Ничего криминального тут не вижу. Плюс это очень удобно, так как при обновлении поля AMOUNT автоматом обновляются последующие строки - никаких дополнительных запросов выполнять не требуется.

Другие варианты:
1. Обновление через еще один апдейт.
Код: sql
1.
2.
3.
4.
5.
6.
7.
UPDATE TABLE T1
SET
    T1.START = COALESCE((SELECT T2.FINISH FROM TABLE T2 WHERE T2.NROW = T1.NROW - 1), 0)
WHERE
    T1.NROW >= 2-- Два взято для примера
ORDER BY
    T1.NROW


Не проверял, но на 99% уверен, что это так же работать это не будет.
2. Обновление через ХП, которая будет пересчитывать поле START, начиная со следующей строки:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
    FOR SELECT
        T1.NROW,
        COALESCE((SELECT T2.FINISH FROM TABLE T2 WHERE T2.NROW = T1.NROW - 1), 0)
    FROM
        TABLE T1
    WHERE
        T1.NROW > :NROW)
    ORDER BY
        T1.NROW
    INTO
        :TMP_NROW,
        :START
    DO
        UPDATE TABLE
        SET
            START = :START
        WHERE
            (NROW = :TMP_NROW)
            AND (START IS DISTINCT FROM :START)


По сути это вариант на триггере, только с необходимостью дополнительного вызова хранимки после изменения данных.
Остановился на этом варианте, так как ничего другого придумать не могу.
...
Рейтинг: 0 / 0
Вопрос по стабильному курсору FB 3
    #39638905
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CyberMax,

при изменении AMOUNT прибавь дельту к AMOUNT и FINISH в текущей записи и прибавь ту же дельту к START и FINISH всем последующим записям.
Для этого нужен один UPDATE, показать ?

Или ты меняешь AMOUNT массово, более чем одной записи за раз ?
...
Рейтинг: 0 / 0
Вопрос по стабильному курсору FB 3
    #39638912
Фотография CyberMax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvladпри изменении AMOUNT прибавь дельту к AMOUNT и FINISH в текущей записи и прибавь ту же дельту к START и FINISH всем последующим записям.
Для этого нужен один UPDATE, показать ?
Мысль понял, попробую через дельту.

hvladИли ты меняешь AMOUNT массово, более чем одной записи за раз ?
Да. Проблема в том, что в примере NROW - 1 колонка. А в реальности уникальный код строки состоит из трех колонок. Для большей ясности могу сказать, какие - это код абонента, которых 200 тысяч, код услуги (например, горячая вода, отопление, электричество) и месяц (январь 2018, февраль 2018 и т.д.). В большинстве случаев изменение делается по условию двух из них - абонент и месяц - то есть одним апдейтом обновляется AMOUNT у нескольких услуг.
...
Рейтинг: 0 / 0
Вопрос по стабильному курсору FB 3
    #39638931
Фотография CyberMax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Переделал логику, благо потребовалось мало изменений - убрал обновление сальдо через триггер, сделал обновление сальдо одним апдейтом на значение дельты в хранимке, которая обновляла суммы в записи. Потестил - вроде работает. Владу спасибо за наводку.
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Вопрос по стабильному курсору FB 3
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]