Postgres 9.1 の plpgsql でトリガーを作成しています。指定されたアクションを監査テーブルに記録できるように、UPDATE の SET 句で発行された列名を取得できる必要があります。Postgres ドキュメントの例は単純で、私のニーズには不十分です。私は何日もインターネットを検索しましたが、ここでやりたいことを達成しようとする他の例を見つけることができません.
私はこれをすぐに解決するためにタイトなスケジュールを組んでいます。私は Tcl を知らないので、現時点では pl/Tcl は問題外です。pl/Perl は機能するかもしれませんが、どこから始めればよいかわかりません。また、移植性とメンテナンスのために、可能であれば pl/pgsql でこれを達成する方法を見つけたかったのです。誰かがこれに対する pl/Perl ソリューションを推奨できれば、私は感謝します。
監査される対象テーブルのテーブル構造は次のとおりです。
注: レコード テーブルには他にも多くの列がありますが、簡単にするためにここには記載していません。ただし、トリガーは、行内の任意の列への変更を記録できる必要があります。
CREATE TABLE record (
record_id integer NOT NULL PRIMARY KEY,
lastname text,
frstname text,
dob date,
created timestamp default NOW(),
created_by integer,
inactive boolean default false
);
create sequence record_record_id_seq;
alter table record alter record_id set default nextval('record_record_id_seq');
これが私の監査テーブルです:
CREATE TABLE record_audit (
id integer NOT NULL PRIMARY KEY,
operation char(1) NOT NULL, -- U, I or D
source_column text,
source_id integer,
old_value text,
new_value text,
created_date timestamp default now(),
created_by integer
);
create sequence record_audit_id_seq;
alter table record_audit alter id set default nextval('record_audit_id_seq');
私の目標は、更新されたターゲット record_id (source_id) と更新された列 (source_column) だけでなく、old_value と new_value の詳細も記録する record_audit テーブルのレコード テーブルに INSERTS と UPDATE を記録することです桁。
列の値は、テキストの種類に CAST() する必要があることを理解しています。NEW と OLD にアクセスすることで old_value と new_value にアクセスできると思いますが、UPDATE クエリの SET 句で使用される列名を取得する方法がわかりません。SET 句で指定されたすべての列の record_audit テーブルに新しいレコードを追加するトリガーが必要です。レコードは単純に非アクティブ = 't' に更新されるため、DELETE アクションはありません (したがって、監査テーブルに記録されます)。
これまでの私のトリガーは次のとおりです(明らかに不完全です)。許してください、私は行くにつれてpl/pgsqlを学んでいます。
-- Trigger function for record_audit table
CREATE OR REPLACE FUNCTION audit_record() RETURNS TRIGER AS $$
DECLARE
insert_table text;
ref_col text; --how to get the referenced column name??
BEGIN
--
-- Create a new row in record_audit depending on the operation (TG_OP)
--
IF (TG_OP = 'INSERT') THEN
-- old_value and new_value are meaningless for INSERTs. Just record the new ID.
INSERT INTO record_audit
(operation,source_id,created_by)
VALUES
('I', NEW.record_id, NEW.created_by);
ELSIF (TG_OP = 'UPDATE') THEN
FOR i in 1 .. TG_ARGV[0] LOOP
ref_col := TG_ARGV[i].column; -- I know .column doesn't exist but what to use?
INSERT INTO record_audit
(operation, source_column, source_id, old_value, new_value, created_by)
VALUES
('U', ref_col, NEW.record_id, OLD.ref_col, NEW.ref_col, NEW.created_by);
END LOOP;
END IF;
RETURN NULL; -- result is ignored anyway since this is an AFTER trigger
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER record_audit_trig
AFTER INSERT OR UPDATE on record
FOR EACH ROW EXECUTE PROCEDURE audit_record();
この長く曲がりくねった質問を読んでくれてありがとう!