我有一个维护特定业务交易的表,我们称之为LOANS
。每个记录在任何给定时间都可以具有几个“状态”中的一个,例如“在重新支付/打开”,“默认”,“无效”或“付费”。
记录的状态只能由于应用程序用户采取的“事件”或操作而发生变化(某些事件不会导致状态更改,例如付款会修改记录但不会更改状态)。在跟踪当前状态的同时,我们也可以轻松跟踪将事务置于此状态的“事件”。
我见过其他数据库设置,LOANS
包含状态列,并且字母(甚至是可能状态表的外键)用于指定当前状态。然后,EVENTS
表格的列为FK
到LOANS
。
此解决方案有效,但我担心这会导致数据完整性丢失。换句话说,没有什么可以阻止状态设置为“默认”而没有EVENT
来支持更改。它将完全留给应用程序以确保永远不会发生这种情况(在我看来,此解决方案中没有参照完整性)。
我的备用解决方案是废弃LOANS
中的状态列,而是使用lastEvent
列,这是EVENTS
的FK。然后EVENTS
表将保持事件的“类型”,进而描述状态变化(例如,如果lastEvent
是'支付'类型,那么状态自然是'已付')。 / p>
我的问题是:
如果重要,我正在使用MS SQL SERVER 2005。
答案 0 :(得分:1)
只有您知道在这里没有参照完整性会有什么风险 - 但总的来说,是的,值得设计您的数据库以便您可以使用参照完整性。它可以减少错误,并增加未来开发人员理解您的架构的机会。
我有一个符合......
的架构贷款
Loan_Id(PK)
量 ....
活动
Event_id(PK)
Loan_ID(FK)
Event_type_id(FK)
日期
status_id(fk)
EVENT_TYPE
event_type_id(pk)
描述
状态
status_id(pk)
描述
要查找任何负载的当前状态,您需要在事件表中找到该贷款的最新条目。要查看贷款状态更改的历史记录,您可以查询事件表。
当您录制不改变状态的事件时,带有新事件的记录只包含事件的当前状态 - 因此您可能会获得如下表格:
Event_id Loan_ID Event_type_id Date status_id
------------------------------------------------
1 1 NEW 1 Jan 2011 NEW
2 1 APPROVE 2 Jan 2011 NEW
3 1 DEFAULT 1 Feb 2011 DEF
...
这样,您始终可以通过查找最新记录来检索当前状态。
它大大降低了bug的风险 - 如果你的“事件”逻辑发生变化,而事件确实改变了贷款的状态,你只需要在一个地方改变它 - 在事件中创建记录的代码数据库。您不必记住也要更改“贷款”记录。
至于性能 - 如果你真的需要,我只会优化它 - 在一个调整良好的数据库上,join和max不应该是show stoppers。
您可以通过创建一个映射有效状态转换及其相关事件的表来优化模型;根据您的数据库,您可以通过触发器强制执行此操作。
我认为这比“最后一个事件”外键更好,因为它是多余的 - 根据定义,最后一个事件是该贷款的MAX(日期)记录。
答案 1 :(得分:0)
我认为您对诚信的关注是有效的。您已经指定了一个业务规则,指出实际上Status不是一个可推断的可写属性 - 来自事件。
根据您的活动数据,我将其设为computable column。
只能猜测你的数据库实现,所以另一种选择是触发器更新列,但是你如何确保其只读? (大概有锁/权限)