当员工更改产品名称,选项名称或价格的信息时。它应该将数据插入到历史日志中以及谁完成它。
项目表:
item_id (PK)
item_name
item_description
注意:商品价格位于item_options表
中item_options表:
option_id (PK)
item_id (FK)
option_name
option_price
一个项目可以有一个或多个选项。
如果我想更改名称items.item_name
,它应该将当前记录复制到历史记录表,从items
表中删除当前记录,然后在{中插入新记录和新信息{1}}表?
items
怎么样,那怎么办?如果特定item_id有多个选项,那么这是否意味着我需要将选项复制到历史表中?
item_options
和items
的审核日志记录/历史记录表应该是什么样的?
由于
答案 0 :(得分:5)
您的审核数据应按表存储,而不是全部存储在一个位置。您要做的是为要跟踪的每个表创建一个审计表,并创建触发器以在审计表中为审计表上的任何数据操作操作创建记录。
绝对建议在DELETE
和items
表上禁止item_options
操作 - 添加item_active
和item_option_active
等标记,以便您可以软删除它们。在您执行的操作中,例如存储参考过去订购的产品的发票,并且需要数据用于历史报告目的,而不是用于日常使用。
您的审计表不是您应该用来引用旧数据的东西,您的普通数据模型应该支持简单地“隐藏”可能仍在使用它的旧数据,并存储将改变的多个数据版本随着时间的推移。
对于审核,存储最后一个用户的用户名以修改给定记录也很有用 - 当从Web应用程序使用时,您不能使用MySQL的USER()
函数来获取有关谁记录的任何有用信息上。添加列并填充它意味着您可以在审计触发器中使用该信息。
NB: 我会假设您不会在正常情况下更改项目ID - 这会使您的审核系统更加复杂。
如果您将活动标记和最后修改过的数据添加到表中,它们将类似于:
mysql> desc items;
+------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+---------+----------------+
| item_id | int(11) | NO | PRI | NULL | auto_increment |
| item_name | varchar(100) | YES | | NULL | |
| item_description | text | YES | | NULL | |
| item_active | tinyint(4) | YES | | NULL | |
| modified_by | varchar(50) | YES | | NULL | |
+------------------+--------------+------+-----+---------+----------------+
mysql> desc item_options;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| option_id | int(11) | NO | PRI | NULL | auto_increment |
| item_id | int(11) | YES | MUL | NULL | |
| option_name | varchar(100) | YES | | NULL | |
| option_price | int(11) | YES | | NULL | |
| option_active | tinyint(4) | YES | | NULL | |
| modified_by | varchar(50) | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
您的审核表需要存储四条额外的信息:
INSERT
或UPDATE
(如果您允许,则为DELETE
)您的审核表应如下所示:
mysql> desc items_audit;
+------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+---------+----------------+
| audit_id | int(11) | NO | PRI | NULL | auto_increment |
| item_id | int(11) | YES | | NULL | |
| item_name | varchar(100) | YES | | NULL | |
| item_description | text | YES | | NULL | |
| item_active | tinyint(4) | YES | | NULL | |
| modified_by | varchar(50) | YES | | NULL | |
| change_by | varchar(50) | YES | | NULL | |
| change_date | datetime | YES | | NULL | |
| action | varchar(10) | YES | | NULL | |
+------------------+--------------+------+-----+---------+----------------+
mysql> desc item_options_audit;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| audit_id | int(11) | NO | PRI | NULL | auto_increment |
| option_id | int(11) | YES | | NULL | |
| item_id | int(11) | YES | | NULL | |
| option_name | varchar(100) | YES | | NULL | |
| option_price | int(11) | YES | | NULL | |
| option_active | tinyint(4) | YES | | NULL | |
| modified_by | varchar(50) | YES | | NULL | |
| change_by | varchar(50) | YES | | NULL | |
| change_date | datetime | YES | | NULL | |
| action | varchar(10) | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
不要在审计表上使用外键;审计表中的行不是他们审计的记录的子行,因此外键没有任何用处。
NB: MySQL不支持多语句类型的触发器,因此每个INSERT
,UPDATE
和{{1}都需要一个触发器(如适用)。
您的触发器只需要将DELETE
所有INSERT
值都放入审计表中。 NEW
表的触发器定义可能是:
items
为/* Trigger for INSERT statements on the items table */
CREATE DEFINER=`root`@`localhost` TRIGGER trigger_items_insert_audit
AFTER INSERT ON items
FOR EACH ROW BEGIN
INSERT INTO items_audit (
item_id, item_name, item_description,
item_active, modified_by, change_by,
change_date, action
) VALUES (
NEW.item_id, NEW.item_name, NEW.item_description,
NEW.item_active, NEW.modified_by, USER(),
NOW(), 'INSERT'
);
END;
/* Trigger for UPDATE statements on the items table */
CREATE DEFINER=`root`@`localhost` TRIGGER trigger_items_update_audit
AFTER UPDATE ON items
FOR EACH ROW BEGIN
INSERT INTO items_audit (
item_id, item_name, item_description,
item_active, modified_by, change_by,
change_date, action
) VALUES (
NEW.item_id, NEW.item_name, NEW.item_description,
NEW.item_active, NEW.modified_by, USER(),
NOW(), 'UPDATE'
);
END;
表创建类似的触发器。
我们上面做的审核将允许您保留任何给定数据库表的历史记录,但创建的数据存储不适合用于需要定期访问的数据。
在电子商务系统中,保留可用的历史数据非常重要,这样您就可以在某些情况下仍然显示旧值时更改属性。
这应该与您的审核解决方案完全分开
存储历史记录的最佳方法是为历史上需要存储的每个属性创建一个历史记录表。 This Stackoverflow question has some good information about keeping a history of a given attribute
在您的情况下,如果您只关心价格和标题,则需要创建一个item_options
表和一个prices
表。每个人都有一个外键到item_titles
表或item_options
表(主表仍然存储当前价格或标题),并且会有价格或头衔及其生效日期。这些表应具有细粒度(可能是基于列的)权限,以避免更新items
日期,以及插入记录后的实际值。
您也应该在这些表格上使用上面的审核解决方案。
答案 1 :(得分:0)
如果您没有一堆约束 - 那么当您通过删除选项条目和visaversa孤立项目条目时,您的数据将会匆忙搞砸。
你要求的东西可以在触发器中完成,但这可能不是你想要的。
如果您有一个包含2个选项的项目,则成像。
现在您更改项目名称,该项目被扣除(并移至历史记录) - 您有不可链接的选项...是您想要的吗?
参考物品的订单或其他东西怎么样?同样的问题。
相反,创建触发器逻辑以仅允许对项目进行“合理”编辑。如果需要,将记录的副本放入并行历史记录表中,但不要删除原始记录。
您还可以考虑在项目或某些日期范围中添加状态列,以便考虑此项目当前可用的想法或您可能需要的其他状态。