Не совсем ответ на вопрос, но слишком большой для комментария ...
Попытка сохранить сводные данные в родительской таблице обычно не очень хорошая идея, так как она подвержена ошибкам и путанице. Например, в этом случае вы хотите добавить значения от leaves
к значениям _used
в leaveentitle
, что предполагает ненулевые значения _used
, что, в свою очередь, означает, что вы намереваетесь запустить его более чем один раз. Но это означает, что вы можете считать одни и те же leaves
данные более одного раза. Если я добавлю данные, как это:
insert into leaveentitle(app_no, ecn, cl_entitled, sl_entitled, lta_entitled)
values (1, 1234, 5, 10, 5);
insert into leaves (app_no, ecn, from_date, to_date, app_date,
no_of_days, leave_type, status)
values (1, 1234, date '2012-01-01', date '2012-01-02', date '2011-12-15',
2, 'SL', 'APPROVED');
... и затем запустите обновление, похожее на @Szilard Barany's (с nvl()
и sum()
), в результате я получаю:
select app_no, ecn, sl_entitled, sl_used, sl_unused
from leaveentitle where app_no = 1 and ecn = 1234;
APP_NO ECN SL_ENTITLED SL_USED SL_UNUSED
------ ------ ----------- ------- ---------
1 1234 10 2
... что выглядит хорошо; но потом, если я добавлю еще одну leaves
запись:
insert into leaves (app_no, ecn, from_date, to_date, app_date,
no_of_days, leave_type, status)
values (1, 1234, date '2012-02-01', date '2012-02-01', date '2012-01-15',
1, 'SL', 'BOOKED');
... и снова обновить, я получаю:
select app_no, ecn, sl_entitled, sl_used, sl_unused
from leaveentitle where app_no = 1 and ecn = 1234;
APP_NO ECN SL_ENTITLED SL_USED SL_UNUSED
------ ------ ----------- ------- ---------
1 1234 10 5
... что явно неправильно, так как я использовал только 3 дня, а не 5. (У меня такое ощущение, что моя компания делает что-то подобное, так как мой баланс отпуска редко бывает точным). Вы можете пересчитать все в своем обновлении, а не добавлять к существующему значению; или вы можете попытаться использовать триггеры для обновления итогов; или вы можете попытаться сохранить состояние, чтобы знать, какие записи leaves
уже включены. Но последние два варианта тоже становятся ужасными, не в последнюю очередь при изменении существующей записи.
Гораздо более простой вариант - удалить столбцы _used
и _unused
из leaveentitle
и сгенерировать значения по мере необходимости, возможно, с помощью представления, облегчающего жизнь вашим пользователям, с помощью запроса типа (угадывание соединения оба условия app_no
и ecn
, но из вопроса не ясно):
select le.app_no, le.ecn, le.sl_entitled,
sum(case when l.leave_type = 'SL' then l.no_of_days else 0 end) as sl_used
from leaveentitle le
join leaves l on l.app_no = le.app_no and l.ecn = le.ecn
group by le.app_no, le.ecn, le.sl_entitled;
APP_NO ECN SL_ENTITLED SL_USED
------ ------ ----------- -------
1 1234 10 3
... или чтобы получить все значения из исходной родительской таблицы:
create or replace view leaveview as
select le.app_no, le.ecn,
le.sl_entitled, ls.sl_used, le.sl_entitled - ls.sl_used as sl_unused,
le.cl_entitled, ls.cl_used, le.cl_entitled - ls.cl_used as cl_unused,
le.lta_entitled, ls.lta_used, le.lta_entitled - ls.lta_used as lta_unused
from leaveentitle le
left join (select l.app_no, l.ecn,
sum(case when l.leave_type = 'SL' then l.no_of_days else 0 end) as sl_used,
sum(case when l.leave_type = 'CL' then l.no_of_days else 0 end) as cl_used,
sum(case when l.leave_type = 'LTA' then l.no_of_days else 0 end) as lta_used
from leaves l
group by l.app_no, l.ecn
) ls on ls.app_no = le.app_no and ls.ecn = le.ecn;
select * from leaveview where app_no = 1 and ecn = 1234;
APP_NO ECN SL_ENTITLED SL_USED SL_UNUSED CL_ENTITLED CL_USED CL_UNUSED LTA_ENTITLED LTA_USED LTA_UNUSED
------ ------ ----------- ------- --------- ----------- ------- --------- ------------ -------- ----------
1 1234 10 3 7 5 0 5 5 0 5
Это также дает вам возможность легко добавлять дополнительные производные значения, такие как разделение на основе status
, просто добавив его в представление, а не добавляя еще один сложный слой вычисления и где-то обновляя.