Database design 如何使用适当的db约束在数据库中保存实体的最新状态

Database design 如何使用适当的db约束在数据库中保存实体的最新状态,database-design,database-schema,data-integrity,Database Design,Database Schema,Data Integrity,我浏览了几个问题,然后写了我自己的,确切地说是3个。我的db很简单,我是一个希望每个模块都能约束事情的人,所以如果其他模块功能不正常,它不会破坏逻辑 我拥有的 我有一个表Book,我想跟踪它的状态,有一个BookStatus表,它可以有图书的状态,如已接受、正在生产、排版、打印等。该表有以下模式 BookStatus[BookID,StatusID,Date] 日期字段可为空,表示此状态结束的日期,如果为空,则表示这是当前状态。因此,要获取当前状态,我们需要执行以下查询: *从BookStatu

我浏览了几个问题,然后写了我自己的,确切地说是3个。我的db很简单,我是一个希望每个模块都能约束事情的人,所以如果其他模块功能不正常,它不会破坏逻辑

我拥有的

我有一个表Book,我想跟踪它的状态,有一个BookStatus表,它可以有图书的状态,如已接受、正在生产、排版、打印等。该表有以下模式

BookStatus[BookID,StatusID,Date]

日期字段可为空,表示此状态结束的日期,如果为空,则表示这是当前状态。因此,要获取当前状态,我们需要执行以下查询:

*从BookStatus中选择*,其中BookID=123,日期为空*

问题

问题是,表中没有约束,其中一个BookID不能有多个空字段,因为一本书一次只能处于一种状态。因此,当有数十个应用程序同时更新db和手动干预时,我们会遇到这样的场景:一本书的状态有多个空值,或者某个时候没有空值

我的解决方案

我唯一能想到的就是在Book表中添加一个Currentstatus字段,每当我更新状态时,我也会更新Book表,但这也不能解决我的问题

问题

我想知道

  • 目前的方法已经足够好了

  • 在当前场景中,是否有其他方法可以确保数据完整性

  • 当前设计:
    如果应用程序处于高并发状态,则需要使用。
    没有这一点是不可避免的。
    控制电流的已知方法如下:

    • 乐观:检查事务是否符合完整性规则,如向任何表中添加类似时间戳的列(行版本),检查更新记录的时间戳是否等于现有行的时间戳。
      由于时间戳不匹配,用户将遭受
      事务中止的痛苦

      在繁重的跨国环境中不适用
    • 悲观:序列化对共享资源的访问,例如为每个事务锁定表记录。
      性能降低和遇到
      超时异常将是副作用
      
    新设计:
    防止对大量并发资源进行更新(表)
    更改
    BookStatus
    (我更喜欢BookTransaction)的设计,任何交易都将导致
    insert
    DML。
    交易日期字段将是必需的。
    图书的最后状态将通过查询或视图根据最后交易日期或序列提取。

    我在银行业遇到了一个问题,当账户在借方/贷方操作之间共享时,从银行分行.Net客户端、网上银行J2EE web服务、基于卡交换C的主机等不同平台开始。。。双面承诺。
    我们尝试了所有解决方案。新设计救了我们。

    请注意,没有一种解决方案是完美的,没有副作用。

    当前设计:
    如果应用程序处于高并发状态,则需要使用。
    没有这一点是不可避免的。
    控制电流的已知方法如下:

    • 乐观:检查事务是否符合完整性规则,如向任何表中添加类似时间戳的列(行版本),检查更新记录的时间戳是否等于现有行的时间戳。
      由于时间戳不匹配,用户将遭受
      事务中止的痛苦

      在繁重的跨国环境中不适用
    • 悲观:序列化对共享资源的访问,例如为每个事务锁定表记录。
      性能降低和遇到
      超时异常将是副作用
      
    新设计:
    防止对大量并发资源进行更新(表)
    更改
    BookStatus
    (我更喜欢BookTransaction)的设计,任何交易都将导致
    insert
    DML。
    交易日期字段将是必需的。
    图书的最后状态将通过查询或视图根据最后交易日期或序列提取。

    我在银行业遇到了一个问题,当账户在借方/贷方操作之间共享时,从银行分行.Net客户端、网上银行J2EE web服务、基于卡交换C的主机等不同平台开始。。。双面承诺。
    我们尝试了所有解决方案。新设计救了我们。


    请注意,没有一种解决方案是完美的,没有副作用。

    此表的自然主键是{book_id,The_date},它需要_date不可为空。因此:要么改变逻辑,使记录的MAX(日期)为currend状态,要么将该表拆分为一个状态表和一个单独的status\u history表。顺便说一句:“日期”是一个列的坏名字;你能给你的孩子取名为“kid”吗?是的,Max(date)很好,但你不认为它会比空检查慢吗?此外,它与null相比没有任何显著的优势,因为我们面临的问题通常不是状态被复制,而是多个状态都是null,即([123,1,null][123,2,null]),它可能慢,也可能慢;这也是正确的。Whis正是使其
    datenotnull
    的原因。此表的自然主键是{book\u id,the\u DATE},这将需要该\u DATE不可为NULL。因此:要么改变逻辑,使记录的MAX(日期)为currend状态,要么将该表拆分为一个状态表和一个单独的status\u history表。顺便说一句: