研究室でコンピュータの使用状況を追跡するためのシステムがあります。少し単純化すると、次のようになります。
- マシンはラボに関連付けられています。
- マシンには、ユーザーがログインおよびログアウトすると自動的に更新されるバイナリの logged_in 状態があります。
ラボに関連付けられたシートの総数と、そのラボで現在使用されている数を収集する、ラボをキーとするビューがあります。
私がやりたいのは、時間の経過に伴うラボ人口の変化を追跡する履歴または監査テーブルを追加することです。マシン テーブルが変更されるたびに、ラボ履歴テーブルに時間とラボの総人口を格納するトリガーがマシン テーブルにありました。問題は、ラボの新しい合計を取得するために、マシン テーブルの他の値を調べなければならないことです。これにより、テーブル変更エラーが発生します。
ここや他の場所で見つけたいくつかのことは、変更されたラボを追跡するためのパッケージを作成する必要があることを示唆しています. before トリガーを使用してリストをクリアし、row トリガーを使用して変更された各 labid を保存し、after トリガーを使用して履歴テーブルを更新し、id がリストにあるラボのみの新しい値を使用します。私はそれを試しましたが、パッケージテーブルに保存した値にアクセスする方法がわかりません(または、そもそもそれらを適切に保存している場合でも)。間違いなく明らかなように、私は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;
/
一方で、パッケージよりも優れた全体的なアプローチがあれば、私はすべて耳にします。