Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 Триггер на обновления счетчика (много операций)  [new]
z3r9
Member

Откуда:
Сообщений: 233
Есть таблицы:

accounts
id
notifications (число не просмотренных уведомлений)

notifications
id
account_id
status (0-просмотрено, 1-не просмотрено)

1. при добавлении записи в notifications если status=1, обновляется счетчик accounts.notifications = + 1
2. при обновлении status в notifications с 1 на 0 обновляется счетчик accounts.notifications = - 1
3. при удалении notifications если status=1 в accounts.notifications = - 1

Это я сделал, для программы все работает, и вот теперь думаю чтобы не нарушалась целостность (accounts.notifications показывал правильное значение) если в БД записи добавлять вручную. Нужно сделать:

4. при добавлении записи в notifications если status=0, не обновляется счетчик accounts.notifications (у меня так и есть)
5. при обновлении status в notifications с 0 на 1 обновляется счетчик accounts.notifications = + 1

Как сделать 5 пункт 1 триггером? Все остальное сделал так:

CREATE OR REPLACE TRIGGER NOTIFICATIONS_COUNT_TRG
  AFTER INSERT OR UPDATE OR DELETE ON notifications
  FOR EACH ROW WHEN (NEW.status = 1 OR OLD.status = 1)
BEGIN
    IF INSERTING then

    UPDATE accounts
    SET    notifications = notifications + 1
    WHERE  accounts.id = :new.account_id;

    ELSIF UPDATING then

    UPDATE accounts
    SET    notifications = notifications - 1
    WHERE  accounts.id = :old.account_id;

  ELSE

    UPDATE accounts
    SET    notifications = notifications - 1
    WHERE  accounts.id = :old.account_id;

  END IF;

END NOTIFICATIONS_COUNT_TRG;
2 май 15, 13:15    [17593827]     Ответить | Цитировать Сообщить модератору
 Re: Триггер на обновления счетчика (много операций)  [new]
eev
Member

Откуда: -
Сообщений: 1156
z3r9,

SQL> create table accounts
  2  (id number,
  3  notifications number);
Table created
SQL> create table notifications
  2  (id number,
  3  account_id number,
  4  status number);
Table created
SQL> CREATE OR REPLACE TRIGGER NOTIFICATIONS_COUNT_TRG
  2    AFTER INSERT OR UPDATE OR DELETE ON notifications
  3    FOR EACH ROW
  4    WHEN (NEW.status = 1 OR OLD.status = 1)
  5  BEGIN
  6    IF INSERTING then
  7  
  8      UPDATE accounts SET notifications = notifications + 1 WHERE accounts.id = :new.account_id;
  9  
 10    ELSIF UPDATING then
 11  
 12      UPDATE accounts SET notifications = notifications - 1 WHERE accounts.id = :old.account_id;
 13  
 14    ELSE
 15  
 16      UPDATE accounts SET notifications = notifications - 1 WHERE accounts.id = :old.account_id;
 17  
 18    END IF;
 19  
 20  END NOTIFICATIONS_COUNT_TRG;

 21  /
Trigger created


SQL> insert into accounts (id) values(1);
1 row inserted
SQL> insert into notifications values (1,1,1);
1 row inserted
SQL> select * from accounts;
        ID NOTIFICATIONS
---------- -------------
        1 
SQL> insert into notifications values (1,1,0);
1 row inserted
SQL> select * from accounts;
        ID NOTIFICATIONS
---------- -------------
         1 

автор
для программы все работает
неа, и даже если исправить, ты не используешь самое простое решение.
2 май 15, 14:19    [17594001]     Ответить | Цитировать Сообщить модератору
 Re: Триггер на обновления счетчика (много операций)  [new]
z3r9
Member

Откуда:
Сообщений: 233
eev, работает, я думаю потому что у вас notifications number = null. А какое решение проще?
2 май 15, 15:49    [17594303]     Ответить | Цитировать Сообщить модератору
 Re: Триггер на обновления счетчика (много операций)  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 54396
    UPDATE accounts
    SET    notifications = notifications + nvl(:new.status, 0) - nvl(:old.ststus, 0);
    WHERE  accounts.id = :old.account_id;
2 май 15, 15:57    [17594318]     Ответить | Цитировать Сообщить модератору
 Re: Триггер на обновления счетчика (много операций)  [new]
eev
Member

Откуда: -
Сообщений: 1156
z3r9
eev, работает, я думаю потому что у вас notifications number = null. А какое решение проще?

конешно null) другого и не оговорено, и много чего
чем селект не устраивает?
2 май 15, 17:01    [17594458]     Ответить | Цитировать Сообщить модератору
 Re: Триггер на обновления счетчика (много операций)  [new]
z3r9
Member

Откуда:
Сообщений: 233
andreymx, спасибо огромное, я даже не заметил что он в условие попадает, думал нужно добавить OR OLD.status = 0 и тогда все пропало.

eev, а у меня объект (account) сессионный и если так сделать получится сэкономить 1 запрос в БД. Да даже если нужна сортировка по вычисляемому полю то с триггером тоже можно ускорить. Только единственное пока не проверял как будет вести себя при каскадном удалении.
2 май 15, 18:30    [17594596]     Ответить | Цитировать Сообщить модератору
 Re: Триггер на обновления счетчика (много операций)  [new]
eev
Member

Откуда: -
Сообщений: 1156
z3r9
а у меня объект (account) сессионный

account - таблица, не смешивайте в кучу разные понятия, таблица доступна всем, кому определили доступ.
z3r9
и если так сделать получится сэкономить 1 запрос в БД.

ничего не экономишь, вычисляемое поле в запросе, (хибернейты ?), то вьюху, как слой представления данных.
а уж аджаксы и т.д. в фоне все это, и ни у кого голова не болит )
z3r9
Да даже если нужна сортировка по вычисляемому полю то с триггером тоже можно ускорить.

каша, у тебя не вычисляемое поле, а обычное поле, которое изменяешь триггером, навешивая накладных расходов на вставку (в заголовке "много операций" :) ) а вот если бы вычисляемое поле... это другое.
и вот это "если"... ) сделать на будущее, что бы никому не пригодилось
z3r9
Только единственное пока не проверял как будет вести себя при каскадном удалении.

уже говорили, мутация и блокировки.
2 май 15, 19:01    [17594643]     Ответить | Цитировать Сообщить модератору
 Re: Триггер на обновления счетчика (много операций)  [new]
z3r9
Member

Откуда:
Сообщений: 233
eev,

автор
account - таблица, не смешивайте в кучу разные понятия, таблица доступна всем, кому определили доступ.


Использую spring security и через него можно получить пользователя.

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


В этом примере согласен, можно вычисляемое поле сделать. Но когда нужно 100 000 записей отсортировать по вычисляемому полю то будет беда.
2 май 15, 19:59    [17594720]     Ответить | Цитировать Сообщить модератору
 Re: Триггер на обновления счетчика (много операций)  [new]
eev
Member

Откуда: -
Сообщений: 1156
z3r9
eev,
автор
account - таблица, не смешивайте в кучу разные понятия, таблица доступна всем, кому определили доступ.

Использую spring security и через него можно получить пользователя.
автор
Есть таблицы:
accounts

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

В этом примере согласен, можно вычисляемое поле сделать. Но когда нужно 100 000 записей отсортировать по вычисляемому полю то будет беда.

в основе утверждения лежит очередной миф?) т.е. будем показывать список пользователей с подсчетом непрочитаных сообщений, и по ним же (кол-ву) сортировать? как часто будет использоваться такой запрос? каждую минуту, час, для годовой отчетности 31-го декабря?
+ к этому что, сортировку может выполнить ап.сервер.)
сходу не найду пример, но типа так, как по "всяким статусам" посчитать
успехов)
+ имхо, офтоп)
вобще примечательно, использовать сурбд как кучу плоских файлов, типа "наш фреймверк обепечит транзакционность, согласованность, а бд это так - плюшка с боку" не зная механики бд, ну-ну..)
3 май 15, 06:32    [17595266]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить