Как установить только для последней изменённой записи значение одного столбца?
Необходимо обеспечить существование в таблице единственной строки с определенным значением. То есть, чтобы при обновлении и добавлении записей занчение колонкаи текущей запии приобретало значение 1, а все оставшиеся - 0.
Попробовал сделать это триггером. С before insert все нормально. А вот что для update придумать? Или может есть какие-то еще варианты решения помимо триггеров?
Пример:
-- Создаем таблицу
create table tx (
id integer,
val varchar2(100)
);
-- Данные
-- truncate table tx
insert into tx
select level, 0 from dual connect by level < 11;
update tx set val = 1 where id = 5;
commit;
Добавляться может только 1 запись, обновляться тоже.
При добавлении и изменении надо:
- Проставлять прежней записи с
val = 1значение 0 - Для последней изменённой записи желательно принудительно установить
val = 1.
Ответы (1 шт):
В качестве обходного пути решения предложу изменить таблицу:
create table t0 (id int, memo varchar2 (96), val char (1) not null)
/
alter table t0 drop column val
/
alter table t0 add (lastrow char (1) invisible, val char (1) as (nvl (lastrow, '0')) virtual)
/
create index idxt0lastrow on t0 (lastrow)
/
Сушествующие запросы не заметят это изменение таблицы. Теперь, флаг последнего изменения будет хранится только для одной последней записи. Индекс для быстрого поиска с одной единсвенной записью, т.к. NULL значения не индексируются.
В составном триггере для update следует указать все столбцы, которые могут быть изменены, а lastrow во избежании рекурсивного вызова триггера, там должен быть опущен:
create or replace trigger t0lastrowtrig
for insert or update of id,memo on t0 compound trigger
lastchanged rowid;
after each row is
begin
lastchanged := :new.rowid;
end after each row;
after statement is
begin
update t0 set
lastrow = case when lastrow is null then 1 end
where rowid = lastchanged or lastrow=1;
end after statement;
end;
/
Тест и результаты:
insert into t0 (id, memo)
select rownum, 'memo '||rownum from dual connect by level<10;
/
select * from t0
/
ID MEMO VAL
---------- -------- ---
1 memo 1 0
[...]
8 memo 8 0
9 memo 9 1
update t0 set memo = memo||'*'
where id = 5
/
select * from t0
/
ID MEMO VAL
---------- -------- ---
1 memo 1 0
[...]
5 memo 5* 1
[...]
9 memo 9 0