我正在尝试创建触发器,在更新后捕获数据库中的更改。
表 my_table
我正在观看:
表 my_table_log
我正在编写更改以记录它们
到目前为止这是触发器:
CREATE TRIGGER `log_update`
AFTER UPDATE ON `my_table`
FOR EACH ROW
BEGIN
INSERT INTO
`my_table_log`
(
`id`,
`action`,
`column_name`,
`value_before`,
`value_after`,
`who`,
`ts`
)
VALUES
(
NEW.id,
'u',
'name',
OLD.name,
NEW.name,
user(),
NOW()
);
END
问题:如何记录每个列的更改?
问题:只有在name
中列my_table
发生变化时,我才会注意到。我为列age
设置了另一个触发器。如何为每行和每个已更改的列设置触发器?
感谢您的建议/代码/灵感
答案 0 :(得分:1)
您可以在触发器中观看的每个列中使用ifs:
create trigger `log_update`
after update on `my_table`
for each row
begin
if (old.name <> new.name) then
insert into `my_table_log`
(
`id`,
`action`,
`column_name`,
`value_before`,
`value_after`,
`who`,
`ts`
)
values
(
new.id,
'u',
'name',
old.name,
new.name,
user(),
now()
);
end if;
if (old.age <> new.age) then
insert into `my_table_log`
(
`id`,
`action`,
`column_name`,
`value_before`,
`value_after`,
`who`,
`ts`
)
values
(
new.id,
'u',
'age',
old.age,
old.age,
user(),
now()
);
end if;
end
但最好使插入存储过程以避免重复:
create procedure `log_insert`
(
id int(11),
`action` char,
column_name varchar(255),
value_before varchar(255),
value_after varchar(255)
)
begin
insert into `my_table_log`
(
`id`,
`action`,
`column_name`,
`value_before`,
`value_after`,
`who`,
`ts`
)
values
(
id,
`action`,
column_name,
value_before,
value_after,
user(),
now()
);
end
并在你的触发器中调用它:
create trigger `log_update`
after update on `my_table`
for each row
begin
if (old.name <> new.name) then
call log_insert
(
new.id,
'u',
'name',
old.name,
new.name
);
end if;
if (old.age <> new.age) then
call log_insert
(
new.id,
'u',
'age',
old.age,
new.age
);
end if;
end
您可以重复使用存储过程来记录插入和删除触发器中的事件。
使shure在my_table_log中使用复合主键以允许对多个列进行更新。我至少使用了:
primary key(id,column_name,who,ts).
或者使用专用的单列主键来避免主键中的varchars以获得更好的性能。
答案 1 :(得分:0)
另一种方法是将新值与user()和now():
一起记录下来create table my_table_log
( id ...
, name ...
, age ...
, action ...
, who ...
, ts ... )
要确定更改内容,请与上一行进行比较。
然而,在某个时间点确定行的样子是相当昂贵的,您必须在该时间点之前找到最后一个版本。使这更容易的另一个模型是跟踪每行的begin_ts和end_ts:
create table my_table_log
( id ...
, name ...
, age ...
, action ...
, who ...
, begin_ts ...
, end_ts ...)
插入触发器使用begin_ts = now()和end_ts = null添加行的副本。更新触发器更新end_ts = now(),其中end_ts为null并插入类似于insert触发器的行。删除触发器更新end_ts,并可能与删除该行的人一起添加副本。确定ts t处的行是where t between start_ts and end_ts