У меня есть система для отслеживания использования компьютеров в лаборатории. Немного упрощая, получается:
- Машины связаны с лабораторией.
- Машины имеют двоичное состояние logged_in, которое автоматически обновляется при входе и выходе пользователей.
В лаборатории есть представление, которое собирает общее количество рабочих мест, связанных с лабораторией, и текущее количество, используемое для этой лаборатории.
Что я хотел бы сделать, так это добавить историю или таблицу аудита, которая будет отслеживать изменения в численности лаборатории с течением времени. У меня был триггер в таблице машин, чтобы сохранять время и общее количество лабораторий в моей таблице истории лабораторий каждый раз, когда таблица машин менялась. Проблема в том, что для того, чтобы получить новую сумму для лаборатории, я должен проверить другие значения в таблице машины. Это приводит к ошибке изменения таблицы.
Некоторые вещи, которые я нашел здесь и в других местах, предложили мне создать пакет для отслеживания изменяемых лабораторий. Используйте триггер «до» для очистки списка, триггер «строка» для сохранения каждой измененной лабиды и триггер «после» для обновления таблицы истории новыми значениями только для тех лабораторий, идентификаторы которых есть в списке. Я пробовал это, но не могу понять, как получить доступ к значениям, которые я сохранил в таблице пакетов (или даже правильно ли они хранятся в первую очередь). Как, без сомнения, будет очевидно, я не знаком с пакетами PL/SQL и табличными переменными - весь синтаксис обращения к записям таблицы, таким как массивы, показался мне смутно еретическим, хотя и невероятно полезным, если он работает. Таким образом, большая часть приведенного ниже просто скопирована и адаптирована из других решений, которые я нашел, но они не касались того, как на самом деле использовать мою таблицу измененных лаблоцидов, предполагая, что она изначально создана правильно. Следующее просто говорит мне, что pg_machine_in_use_pkg.changedlablocids не существует, когда я пытаюсь скомпилировать окончательный триггер.
create or replace package labstats_adm.pg_machine_in_use_pkg
as
type arr is table of number index by binary_integer;
changedlablocids arr;
empty arr;
end;
/
create or replace trigger labstats_adm.pg_machine_in_use_init
before insert or update
on labstats_adm.pg_machine
begin
-- begin each update with a blank list of changed lablocids
pg_machine_in_use_pkg.changedlablocids := pg_machine_in_use_pkg.empty;
end;
/
--
create or replace trigger labstats_adm.pg_machine_in_use_update
after insert or update of in_use,lablocid
on labstats_adm.pg_machine
for each row
begin
-- record lablocids - old and new - of changed machines
if :new.lablocid is not null then
pg_machine_in_use_pkg.changedlablocids( pg_machine_in_use_pkg.changedlablocids.count+1 ) := :new.lablocid;
end if;
if :old.lablocid is not null and :old.lablocid != :new.lablocid then
pg_machine_in_use_pkg.changedlablocids( pg_machine_in_use_pkg.changedlablocids.count+1 ) := :old.lablocid;
end if;
end;
create or replace trigger labstats_adm.pg_machine_lab_history
after insert or update of in_use,lablocid
on labstats_adm.pg_machine
begin
-- for each lablocation we just logged a change to, update that labs history
insert into labstats_adm.pg_lab_history (labid, time, total_seats, used_seats)
select labid, systimestamp, total_seats, used_seats
from labstats_adm.lab_usage
where labid in (
select distinct labid from pg_machine_in_use_pkg.changedlablocids
);
end;
/
С другой стороны, если есть лучший общий подход, чем пакет, я весь внимание.