Database 如何表示当前状态或状态并维护数据/引用完整性?-数据库设计

Database 如何表示当前状态或状态并维护数据/引用完整性?-数据库设计,database,database-design,relational-database,Database,Database Design,Relational Database,我有一个表,用于维护特定的业务事务,我们称之为LOANS。每个记录在任何给定时间都可以有几个“状态”中的一个,例如“重新付款/打开”、“默认”、“作废”或“已付款” 记录的状态只能因“事件”或应用程序用户采取的操作而更改(某些事件不会导致状态更改,例如付款会修改记录,但不会更改状态)。在跟踪当前状态的同时,我们可以轻松地跟踪使事务处于这种状态的“事件”,这一点也很重要 我见过其他数据库的设置,例如LOANS包含一个status列,并使用一个字母(甚至是可能状态表的外键)来指定当前状态。然后,事件

我有一个表,用于维护特定的业务事务,我们称之为
LOANS
。每个记录在任何给定时间都可以有几个“状态”中的一个,例如“重新付款/打开”、“默认”、“作废”或“已付款”

记录的状态只能因“事件”或应用程序用户采取的操作而更改(某些事件不会导致状态更改,例如付款会修改记录,但不会更改状态)。在跟踪当前状态的同时,我们可以轻松地跟踪使事务处于这种状态的“事件”,这一点也很重要

我见过其他数据库的设置,例如
LOANS
包含一个status列,并使用一个字母(甚至是可能状态表的外键)来指定当前状态。然后,
事件
表中有一列是
FK
贷款

此解决方案可行,但我担心这可能会导致数据完整性丢失。换句话说,没有任何东西可以阻止将状态设置为“defaulted”(默认),并且没有
事件来支持更改。这将完全由应用程序来确保不会发生这种情况(在我看来,这个解决方案中没有引用完整性)

我的替代解决方案是取消
LOANS
中的status列,而是使用
lastEvent
列,该列是
事件的FK。
EVENTS
表将维护事件的“类型”,该类型将依次描述状态变化(例如,如果
lastEvent
为“payoff”类型,则状态自然为“payed”)

我的问题是:

  • 我是否应该关心数据的完整性(这是一件很常见的事情,因为这样做是可以的)
  • 我提出的解决方案是合理的,还是有更好的解决方案
  • 我的解决方案中是否有任何陷阱需要注意

  • 如果有必要,我使用的是MS SQL SERVER 2005。

    我认为您对完整性的关注是正确的。您指定了一个业务规则,该规则声明,实际上状态不是一个可写属性,它是从事件推断出来的

    我会根据你的事件数据做一个调查

    我们只能猜测您的db实现,所以另一种选择是触发器更新列,但如何确保它是只读的?(可能带有锁/权限)

  • 只有您知道如果您在这里没有引用完整性会有什么风险,但是一般来说,是的,设计数据库以便使用引用完整性是值得的。它减少了错误,增加了未来开发人员理解您的模式的机会

  • 我会有一个大致如下的模式

    贷款


    贷款Id(PK)

    数量

    事件


    事件id(主键)

    贷款ID(FK)

    事件类型标识(FK)

    日期

    身份证(fk)

    事件类型


    事件类型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
    ...
    
    这样,您总是通过查找最新记录来检索当前状态

    它极大地降低了错误的风险——如果“事件”的逻辑发生了变化,并且某个事件确实改变了贷款的状态,那么您只需在一个地方进行更改——即在事件数据库中创建记录的代码。您不必记住也要更改“贷款”记录

    至于性能——我只会在您真正需要的时候对此进行优化——在经过良好调优的数据库上,join和max不应该是show stopper

    您可以通过创建映射有效状态转换及其关联事件的表来优化模型;根据您的数据库,您可以通过触发器强制执行此操作


    我认为这比“last event”外键更好,因为它是多余的-根据定义,last event是该贷款的最大(日期)记录。

    我使用的是SQL SERVER 2005,为了清晰起见,在问题中添加了它。计算列在2005年可用,请参阅链接顶部的“其他版本”,因为某些事件不会更改状态,这也是我选择不看最后一个事件的原因之一(但也许我可以推断,不改变状态的事件需要一个初始状态来开始)。另一个原因是我认为在lastEvent中存储它可能比每次我想要某个特定状态的所有项目时调用MAX(date)要快(这种类型的调用会经常发生)。