很长一段时间以来,我都是使用脚本将信息复制到另一个表中
因为 MySQL 当时不支持触发器
触发更有效地跟踪一切。
如果旧值被更改,此触发器将把它复制到历史表中
当某人编辑一行时。 Editor ID和 last mod存储在
每次有人编辑该行时,都会返回原始表; 时间对应于
变成现在的样子。
DROP TRIGGER IF EXISTS history_trigger $$
CREATE TRIGGER history_trigger
BEFORE UPDATE ON clients
FOR EACH ROW
BEGIN
IF OLD.first_name != NEW.first_name
THEN
INSERT INTO history_clients
(
client_id ,
col ,
value ,
user_id ,
edit_time
)
VALUES
(
NEW.client_id,
'first_name',
NEW.first_name,
NEW.editor_id,
NEW.last_mod
);
END IF;
IF OLD.last_name != NEW.last_name
THEN
INSERT INTO history_clients
(
client_id ,
col ,
value ,
user_id ,
edit_time
)
VALUES
(
NEW.client_id,
'last_name',
NEW.last_name,
NEW.editor_id,
NEW.last_mod
);
END IF;
END;
$$
另一个解决方案是保留一个 Revison 字段,并在保存时更新该字段。您可以确定 max 是最新的修订,或者0是最新的一行。这取决于你。
每次您想要更改客户记录时,不是更新记录,而是将当前记录上的 VALID _ UNTIL 设置为 NOW () ,并插入一条带有 VALID _ FROM (NOW)和空 VALID _ UNTIL 的新记录。将“ CUSTOMER _ USER”状态设置为当前用户的登录 ID (如果需要保留该 ID)。如果需要删除客户,可以使用 CUSTOMER _ STATUS 标志来表明这一点——您可能永远不会从这个表中删除记录。
这样,您总是可以找到某个给定日期的 customer 表的状态-地址是什么?他们改名字了吗?通过连接到其他具有相似的 valid_ from 和 valid_ until 日期的表,您可以历史性地重新构建整个图片。若要查找当前状态,请搜索带有空 VALID _ UNTIL 日期的记录。
CREATE TABLE MyDB.data_history LIKE MyDB.data;
ALTER TABLE MyDB.data_history MODIFY COLUMN primary_key_column int(11) NOT NULL,
DROP PRIMARY KEY, ENGINE = MyISAM, ADD action VARCHAR(8) DEFAULT 'insert' FIRST,
ADD revision INT(6) NOT NULL AUTO_INCREMENT AFTER action,
ADD dt_datetime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER revision,
ADD PRIMARY KEY (primary_key_column, revision);
然后你创造了触发器:
DROP TRIGGER IF EXISTS MyDB.data__ai;
DROP TRIGGER IF EXISTS MyDB.data__au;
DROP TRIGGER IF EXISTS MyDB.data__bd;
CREATE TRIGGER MyDB.data__ai AFTER INSERT ON MyDB.data FOR EACH ROW
INSERT INTO MyDB.data_history SELECT 'insert', NULL, NOW(), d.*
FROM MyDB.data AS d WHERE d.primary_key_column = NEW.primary_key_column;
CREATE TRIGGER MyDB.data__au AFTER UPDATE ON MyDB.data FOR EACH ROW
INSERT INTO MyDB.data_history SELECT 'update', NULL, NOW(), d.*
FROM MyDB.data AS d WHERE d.primary_key_column = NEW.primary_key_column;
CREATE TRIGGER MyDB.data__bd BEFORE DELETE ON MyDB.data FOR EACH ROW
INSERT INTO MyDB.data_history SELECT 'delete', NULL, NOW(), d.*
FROM MyDB.data AS d WHERE d.primary_key_column = OLD.primary_key_column;
你完蛋了。现在,‘ MyDb.data’中的所有插入、更新和删除都将记录在‘ MyDb.data _ history’中,给出一个类似这样的历史表(去掉人为设计的‘ data _ column’列)
ID revision action data columns..
1 1 'insert' .... initial entry for row where ID = 1
1 2 'update' .... changes made to row where ID = 1
2 1 'insert' .... initial entry, ID = 2
3 1 'insert' .... initial entry, ID = 3
1 3 'update' .... more changes made to row where ID = 1
3 2 'update' .... changes made to row where ID = 3
2 2 'delete' .... deletion of row where ID = 2
CREATE VIEW data_history_changes AS
SELECT t2.dt_datetime, t2.action, t1.primary_key_column as 'row id',
IF(t1.a_column = t2.a_column, t1.a_column, CONCAT(t1.a_column, " to ", t2.a_column)) as a_column
FROM MyDB.data_history as t1 INNER join MyDB.data_history as t2 on t1.primary_key_column = t2.primary_key_column
WHERE (t1.revision = 1 AND t2.revision = 1) OR t2.revision = t1.revision+1
ORDER BY t1.primary_key_column ASC, t2.revision ASC
历史表和数据表中的字段匹配非常重要。或者,更确切地说,您的数据表没有比历史表更多的列。否则,对数据表的插入/更新/del 查询将失败,当对历史表的插入在查询中放入不存在的列时(由于触发器查询中的 d *) ,触发器将失败。如果 MySQL 具有类似模式触发器的东西,那将是非常棒的,在这里,如果向数据表中添加了列,您可以修改历史表。MySQL 现在有这个吗?这些天我确实做出了反应
Users
-------------------------------------------------
id | name | address | phone | email | created_on | updated_on
业务需求发生了变化,我们需要检查用户以前的所有地址和电话号码。
新模式如下所示
Users (the data that won't change over time)
-------------
id | name
UserData (the data that can change over time and needs to be tracked)
-------------------------------------------------
id | id_user | revision | city | address | phone | email | created_on
1 | 1 | 0 | NY | lake st | 9809 | @long | 2015-10-24 10:24:20
2 | 1 | 2 | Tokyo| lake st | 9809 | @long | 2015-10-24 10:24:20
3 | 1 | 3 | Sdny | lake st | 9809 | @long | 2015-10-24 10:24:20
4 | 2 | 0 | Ankr | lake st | 9809 | @long | 2015-10-24 10:24:20
5 | 2 | 1 | Lond | lake st | 9809 | @long | 2015-10-24 10:24:20
要查找任何用户的当前地址,我们使用修订版 DESC 和 LIMIT 1搜索 UserData
在某段时间内获取用户的地址
我们可以使用 create _ on between (date1,date 2)