Я создал 2 стола: INFORMATION
И FEED
.Как разрешить столбцу значения автоматически отражать, когда значение вставлено/обновлено/удалено в/из другого столбца в той же таблице?
INFORMATION has 2 attributes : ID(Primary Key), TOT_AMOUNT.
FEED has 4 attributes : ID(Foreign key refer INFORMATION(ID)), S_AMOUNT, S_DATE, TOT_REM.
Теперь я должен вставить/обновить/удалить значения в/из TOT_REM
, на основе ввода/удаления/обновления S_AMOUNT
и TOT_AMOUNT
.
Выборочные содержание:
INFORMATION Table
------------------
ID | TOT_AMOUNT
1 | 100
2 | 20
3 | 50
...
FEED Table
----------------------------------------
ID | S_AMOUNT | S_DATE | TOT_REM
1 | 10 |10.10.2010| 90
1 | 10 |13.10.2010| 80
1 | 30 |17.10.2013| 50
1 | 10 |20.10.2016| 40
...
Нам нужно автоматически вставить значение в TOT_REM
атрибут, на основе обновления/вставки/удаления операции, выполняемые на S_AMOUNT
, с помощью TOT_AMOUNT
& S_AMOUNT
.
В любое время, TOT_REM не может быть меньше 0. И, TOT_REM должен быть автоматически вставлен/удалены/обновлены таким образом, что
TOT_REM for i(at a specific date) = (TOT_AMOUNT for ID=i) -
SUM(S_AMOUNT of all instances of ID=i,
which is later than the S_DATE for ID=i);
Таким образом, при условии, если мы удаляем 2-й кортеж (1, 10, '13 .10.2010' , 80), отраженное состояние BR_FEED
должно быть:
FEED Table
----------------------------------------
ID | S_AMOUNT | S_DATE | TOT_REM
1 | 10 |10.10.2010| 90
1 | 30 |17.10.2013| 60
1 | 10 |20.10.2016| 50
...
я написал триггер, который терпит неудачу, показывающий
ORA-04091: table SSUMAN.FEED is mutating, trigger/function may not see it
Кода триггера:
CREATE OR REPLACE TRIGGER BR_INSERT_TRB
AFTER DELETE OR INSERT OR UPDATE OF S_AMOUNT ON FEED
FOR EACH ROW
BEGIN
IF DELETING THEN
UPDATE FEED bf
SET bf.TOT_REM = bf.S_AMOUNT + :OLD.S_AMOUNT;
END IF;
IF INSERTING THEN
INSERT INTO FEED (TOT_REM) VALUES(
((SELECT TOT_AMOUNT FROM INFORMATION bi WHERE bi.ID=:NEW.ID) -
(SELECT SUM(S_AMOUNT) FROM FEED bf where bf.ID=:NEW.ID) -
:NEW.S_AMOUNT);
END IF;
IF UPDATING THEN
UPDATE FEED bf
SET bf.TOT_REM = (SELECT TOT_AMOUNT FROM BR_INFORMATION bi WHERE bi.ID=bf.ID) -
(SELECT SUM(S_AMOUNT) FROM FEED bf where bf.ID=:NEW.ID) -
:NEW.S_AMOUNT
WHERE :NEW.ID IS NOT NULL;
END IF;
END;
Вопросы:
- испорчен ли такой подход? Не могу ли я достичь того, чего хочу, таким образом? [ДОПОЛНИТЕЛЬНО]
- Есть ли какие-либо возможности для просмотра? Я не могу думать в этой строке! Возможно, отсутствие опыта ... [НЕОБЯЗАТЕЛЬНО]
- Любой лучший подход, так что значения TOT_REM могут быть автоматически отражены? [ОБЯЗАТЕЛЬНО ОТВЕТИТЬ]
Когда вы говорите: «TOT_REM не может быть меньше 0» - вы имеете в виду это как часть логики вычисления TOT_REM, или если нарушающая вставка/обновление/удаление будет ОТКАЗЫВАЕТСЯ, потому что это приведет к тому, что TOT_REM станет отрицательным? Они совершенно разные и решаются по-разному. – mathguy
@mathguy - Он должен быть отклонен, спасибо, что попросил разъяснений. Требуется любая другая деталь? –
Я вижу здесь несколько трудностей. Самый большой - это вычисление TOT_REM в начале. Если вы удалите строку 10.10.2010, то TOT_REM в следующей строке необходимо прочитать из таблицы INFORMATION, а не из строки над ней. Если вы добавите строку выше первой (выше 10.10.2010), TOT_ROM 10.10.2010 нужно будет рассчитывать на основе строки над ней, а не из ИНФОРМАЦИИ. Еще большая проблема: вы отклоняете строку, потому что это сделает TOT_ROM отрицательным. В более позднее время вы удалите строку со старой датой ... теперь вам нужно вернуть обратно строку, которую вы отклонили вначале? – mathguy