我正在设计这个数据库,它必须保留员工工资和组织内变动的历史记录。基本上,我的设计有 3 个表(我的意思是,还有更多的表,但对于这个问题,我会提到 3 个,所以请耐心等待)。Employee 表(包含最新的薪水、职位数据等)、SalaryHistory 表(薪水、日期、原因等)和 MovementHistory(职务、部门、评论)。我将使用 Linq to Sql,所以我的想法是每次更新员工数据时,旧值都会被复制到各自的历史表中。这是一个好方法吗?我应该使用 Linq to SQL 还是触发器来完成它?感谢您的任何帮助、建议或想法。
5 回答
看看http://www.simple-talk.com/sql/database-administration/database-design-a-point-in-time-architecture。
基本上,这篇文章建议您在需要跟踪历史记录的表中有以下列 -
* DateCreated – the actual date on which the given row was inserted.
* DateEffective – the date on which the given row became effective.
* DateEnd – the date on which the given row ceased to be effective.
* DateReplaced – the date on which the given row was replaced by another row.
* OperatorCode – the unique identifier of the person (or system) that created the row.
DateEffective 和 DateEnd 一起告诉您该行有效的时间(或员工在部门的时间,或他获得特定薪水的时间)。
将该逻辑保留在数据库内部是一个好主意:这基本上就是触发器存在的原因。但是,我要小心地说,因为有很多理由将其保留在外部。很多时候——尤其是使用像 LINQ-to-SQL 这样简单的技术——在外部编写代码更容易。根据我的经验,使用 C#/LINQ 编写该逻辑的人比使用触发器正确编写的人多。
触发器很快 - 它们已编译!但是,它们很容易被误用,并使您的逻辑过于复杂,以至于性能会迅速下降。考虑到您的用例有多简单,我会选择使用 triggers,但这是我个人的情况。
触发器可能会更快,并且不需要“中间人”来完成工作,从而至少消除了一次出错的机会。
根据您选择的数据库,您可以只使用一个表并在其上启用 OID,然后再添加两列,“flag”和“previous”。永远不要更新这个表,只插入。添加一个触发器,以便在为员工#id 添加一行时,将所有具有员工#id 的记录设置为具有“旧”标志,并将新行的“上一个”值设置为前一行。
我认为这属于数据库有两个原因。
首先,中间层来来去去,但数据库永远存在。今年是 Java EJB,明年是 .NET,后年是别的东西。根据我的经验,数据仍然存在。
其次,如果数据库是完全共享的,它不应该依赖每个使用它的应用程序来知道如何维护其数据完整性。我认为这是一个封装数据库的例子。为什么要强制每个客户了解和维护历史?
触发器使您的前端更容易迁移到其他东西,并且无论如何插入/更新/删除数据,它们都会保持数据库的一致性。
此外,在您的情况下,我会将工资直接写入工资历史记录-从您的描述中,我看不出您应该通过员工表上的更新触发器来解决问题的原因。