Модераторы: skyboy
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> триггер вызывает зацикливание 
V
    Опции темы
ksili
Дата 21.8.2008, 07:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

Репутация: нет
Всего: 17



В БД есть таблица с абонентами. У них там есть балансы и номера телефонов. Так вот у нескольких клиентов несколько телефонов и надо синхронизировать их баланс для нескольких записей. Т.е. записей в таблице две, а счёт один. Например, поговорил человек с одного телефона -> с баланса, соответствующего этому номеру, списывается соответствующая сумма -> та же сумма списывается с другого счёта этого абонента (чтобы они были равны)

Я решил это сделать триггером на после обновления (т.к. таких абонентов будет немного):
Код

CREATE OR ALTER TRIGGER T_USERS_AU0 FOR T_USERS
ACTIVE AFTER UPDATE POSITION 0
AS
begin
    if(new.phone='232323') then
        update T_USERS set SUMMA_OST=new.SUMMA_OST where PHONE='454545';
    else if(new.phone='454545') then
        update T_USERS set SUMMA_OST=new.SUMMA_OST where PHONE='232323';
end


Но такой триггер вызывает ошибку 'Too many concurrent executions of the same request', т.к. изменение для одной записи провоцирует update другой, а тот провоцирует update первой, и так до бесконечности.

Как всё-таки добиться синхронизации двух счетов?

СУБД: Firebird 2.0

Это сообщение отредактировал(а) ksili - 21.8.2008, 10:20


--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
Akina
Дата 21.8.2008, 08:11 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 454



Цитата(ksili @  21.8.2008,  08:07 Найти цитируемый пост)
записей в таблице две, а счёт один

А откорректировать структуру?


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
skyboy
Дата 21.8.2008, 08:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 15
Всего: 260



не знаю, что это за БД с такой структурой, но вообще говоря, на клиента заводится счет. И будь на человека зарегистрирована хоть корпоративная сеть в 500 номеров, хоть один номер, деньги списываются со счета, а не с телефонного номера.
PM MAIL   Вверх
ksili
Дата 21.8.2008, 08:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

Репутация: нет
Всего: 17



Долгое время было так: один счёт - один номер. Поэтому практически идентифицировался абонент по номеру, никаких других данных о нем и нету. Но уже тогда было заложено максимум три номера на одном счету, правда это не использовалось.
А сейчас появились корпоративные клиенты и им и три номера мало. Поэтому приходится заводить несколько записей в T_USERS. Добавлять новые поля для номеров считаю неправильным, т.к. во-первых у большинства они так и будут не использоваться, а во-вторых, ну добавлю 10 полей, а когда-нибудь и их не хватит, опять что ли добавлять...


--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
Akina
Дата 21.8.2008, 09:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 454



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


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
jsa
Дата 22.8.2008, 05:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 704
Регистрация: 19.1.2006
Где: Новосибирск

Репутация: нет
Всего: 20



Цитата(ksili @  21.8.2008,  12:07 Найти цитируемый пост)
Но такой триггер вызывает ошибку 'Too many concurrent executions of the same request', т.к. изменение для одной записи провоцирует update другой, а тот провоцирует update первой, и так до бесконечности.

а если попробывать бросать exception
Код

CREATE OR ALTER TRIGGER T_USERS_AU0 FOR T_USERS
ACTIVE AFTER UPDATE POSITION 0
AS
begin
    if(new.phone='232323') then
        update T_USERS set SUMMA_OST=new.SUMMA_OST where PHONE='454545';
    else if(new.phone='454545') then
        update T_USERS set SUMMA_OST=new.SUMMA_OST where PHONE='232323';
    exception;
end

ну примерно так, 
в теории update должен срабоать только один раз, вот как на практике ....




--------------------
Все мы, на перине с песней, строим небо на земле © Ю. Шевчук
PM MAIL ICQ   Вверх
ksili
Дата 22.8.2008, 06:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

Репутация: нет
Всего: 17



jsa, идея интересная, но что-то не получилось. Видимо опыта не хватило. Зато придумал как сделать по-другому. Просто перед апдейтом проверяю, отличается ли сумма от нужной, или нет. И ещё сделал before update, а  не after.
Код

CREATE OR BEFORE TRIGGER T_USERS_BU1 FOR T_USERS
ACTIVE BEFORE UPDATE POSITION 1
declare variable var_sum integer;
AS
begin
    if(new.phone='232323') then
        begin
        select SUMMA_OST from T_USERS where PHONE='454545' into :var_sum;
        if(var_sum<>new.summa_ost) then update T_USERS set SUMMA_OST=new.SUMMA_OST where PHONE='454545';
        end
    else if(new.phone='454545') then
        begin
        select SUMMA_OST from T_USERS where PHONE='232323' into :var_sum;
        if(var_sum<>new.summa_ost) then update T_USERS set SUMMA_OST=new.SUMMA_OST where PHONE='232323';
        end
end



--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




[ Время генерации скрипта: 0.4947 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.