PL/pgSQL: 如何使用 IF NEW.<variable_column_name> <> OLD.<variable_column_name>
PL/pgSQL: How to use IF NEW.<variable_column_name> <> OLD.<variable_column_name>
我对 PL/pgSQL 编程还很陌生。我的 table
中有审计日志更新列的要求
Table
create table sample_table(name varchar(15),city varchar(15),age int,mail varchar(20) primary key);
审计table
create table sample_table__audits_dynamicols(mail varchar(20), columnchanged varchar(10), oldvalue varchar(10), changed_on timestamp(6) NOT NULL)
触发函数
CREATE FUNCTION public.log_sample_table_allchanges() RETURNS trigger AS $BODY$DECLARE
_colname text;
_tablename varchar(15) := 'sample_table';
_schema varchar(15) := 'public';
_changed_on time := now();
BEGIN
FOR _colname IN SELECT column_name FROM information_schema.Columns WHERE table_schema = _schema AND table_name = _tablename LOOP
IF NEW._colname <> OLD._colname THEN
INSERT INTO sample_table__audits_dynamicols(mail,columnchanged, oldvalue ,changed_on)
VALUES(OLD.mail,_colname,OLD.:_colname,_changed_on);
END IF;
END LOOP;
RETURN NEW;
END$BODY$
LANGUAGE plpgsql VOLATILE NOT LEAKPROOF;
触发器
create TRIGGER log_sample_table_allchanges
BEFORE UPDATE
ON SAMPLE_TABLE
FOR EACH ROW
EXECUTE PROCEDURE log_sample_table_allchanges();
要求:每当更改列值时,我想将其记录为
(邮件、列名、列值、日期)
例如:
insert into sample_table (name, mail, city, age) values('kanta','mk@foo.com','hyd',23);
insert into sample_table (name, mail, city, age) values('kmk','mk@gmail.com','hyd',23);
所以当我像下面这样更新时
update sample_table set age=24 where mail='mk@foo.com';
update sample_table set city='bza' where mail='mk@gmail.com'
我要审计table记录喜欢
(mk@foo.com,age,23, timestamp)
(mk@gmail.com, city, hyd, timestamp)
现在我在触发器函数中遇到列比较问题。请帮我改正我的触发器功能以满足我的要求。
您可以使用EXECUTE
动态获取列的值并进行比较。
CREATE OR REPLACE FUNCTION public.log_sample_table_allchanges() RETURNS trigger AS
$BODY$
DECLARE
_colname text;
_tablename varchar(15) := 'sample_table';
_schema varchar(15) := 'public';
_changed_on timestamp := now();
_old_val text;
_new_val text;
BEGIN
FOR _colname IN SELECT column_name FROM information_schema.Columns WHERE table_schema = _schema AND table_name = _tablename
LOOP
EXECUTE 'SELECT .' || _colname || ', .' || _colname
USING OLD,NEW
INTO _old_val, _new_val; --get the old and new values for the column.
IF _new_val <> _old_val THEN
INSERT INTO sample_table__audits_dynamicols(mail,columnchanged, oldvalue ,changed_on)
VALUES(OLD.mail,_colname,_old_val,_changed_on);
END IF;
END LOOP;
RETURN NEW;
END$BODY$
LANGUAGE plpgsql VOLATILE NOT LEAKPROOF;
我不确定您为什么在审核 table 中将 mail
定义为 PRIMARY KEY
,如果更新同一封邮件,将导致 unique constraint
违规两次。
我对 PL/pgSQL 编程还很陌生。我的 table
中有审计日志更新列的要求Table
create table sample_table(name varchar(15),city varchar(15),age int,mail varchar(20) primary key);
审计table
create table sample_table__audits_dynamicols(mail varchar(20), columnchanged varchar(10), oldvalue varchar(10), changed_on timestamp(6) NOT NULL)
触发函数
CREATE FUNCTION public.log_sample_table_allchanges() RETURNS trigger AS $BODY$DECLARE
_colname text;
_tablename varchar(15) := 'sample_table';
_schema varchar(15) := 'public';
_changed_on time := now();
BEGIN
FOR _colname IN SELECT column_name FROM information_schema.Columns WHERE table_schema = _schema AND table_name = _tablename LOOP
IF NEW._colname <> OLD._colname THEN
INSERT INTO sample_table__audits_dynamicols(mail,columnchanged, oldvalue ,changed_on)
VALUES(OLD.mail,_colname,OLD.:_colname,_changed_on);
END IF;
END LOOP;
RETURN NEW;
END$BODY$
LANGUAGE plpgsql VOLATILE NOT LEAKPROOF;
触发器
create TRIGGER log_sample_table_allchanges
BEFORE UPDATE
ON SAMPLE_TABLE
FOR EACH ROW
EXECUTE PROCEDURE log_sample_table_allchanges();
要求:每当更改列值时,我想将其记录为
(邮件、列名、列值、日期)
例如:
insert into sample_table (name, mail, city, age) values('kanta','mk@foo.com','hyd',23);
insert into sample_table (name, mail, city, age) values('kmk','mk@gmail.com','hyd',23);
所以当我像下面这样更新时
update sample_table set age=24 where mail='mk@foo.com';
update sample_table set city='bza' where mail='mk@gmail.com'
我要审计table记录喜欢
(mk@foo.com,age,23, timestamp)
(mk@gmail.com, city, hyd, timestamp)
现在我在触发器函数中遇到列比较问题。请帮我改正我的触发器功能以满足我的要求。
您可以使用EXECUTE
动态获取列的值并进行比较。
CREATE OR REPLACE FUNCTION public.log_sample_table_allchanges() RETURNS trigger AS
$BODY$
DECLARE
_colname text;
_tablename varchar(15) := 'sample_table';
_schema varchar(15) := 'public';
_changed_on timestamp := now();
_old_val text;
_new_val text;
BEGIN
FOR _colname IN SELECT column_name FROM information_schema.Columns WHERE table_schema = _schema AND table_name = _tablename
LOOP
EXECUTE 'SELECT .' || _colname || ', .' || _colname
USING OLD,NEW
INTO _old_val, _new_val; --get the old and new values for the column.
IF _new_val <> _old_val THEN
INSERT INTO sample_table__audits_dynamicols(mail,columnchanged, oldvalue ,changed_on)
VALUES(OLD.mail,_colname,_old_val,_changed_on);
END IF;
END LOOP;
RETURN NEW;
END$BODY$
LANGUAGE plpgsql VOLATILE NOT LEAKPROOF;
我不确定您为什么在审核 table 中将 mail
定义为 PRIMARY KEY
,如果更新同一封邮件,将导致 unique constraint
违规两次。