我有一个用于跟踪实验室中计算机使用情况的系统。稍微简化一下,它可以:
- 机器与实验室相关联。
- 机器具有二进制已登录状态,当用户登录和注销时会自动更新。
有一个锁定在实验室的视图,它收集与实验室相关联的座位总数,以及该实验室当前使用的座位数。
我想做的是添加一个历史记录或审计表,它可以跟踪实验室人口随时间的变化。每次机器表发生变化时,我在机器表上都有一个触发器,用于在我的实验室历史记录表中存储时间和实验室总人数。问题是,为了获得实验室的新总数,我必须检查机器表中的其他值。这会导致表变异错误。
我在这里和其他地方发现的一些东西建议我应该创建一个包来跟踪正在更改的实验室。使用前触发器来清除列表,使用行触发器来存储每个被更改的 labid,并使用后触发器来更新历史记录表,只为那些 id 在列表中的实验室使用新值。我已经尝试过了,但无法弄清楚如何访问我存储在包表中的值(或者即使它首先正确地存储了它们。)毫无疑问,我是不熟悉 PL/SQL 包和表变量 - 引用数组之类的表条目的整个语法让我觉得有点异端,但如果它有效的话却非常有用。所以下面的大部分内容只是从我找到的其他解决方案中复制和改编的,但他们没有 t 延伸至如何实际使用我的已更改 lablocids 表,假设它首先被正确创建。下面简单地告诉我,当我尝试编译最终触发器时,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;
/
另一方面,如果有比包装更好的整体方法,我会全力以赴。