有效管理数据变更

Rob*_*ill 12 php mysql database-design cakephp cakephp-1.3

我有一张名为Bookings的桌子.此表包含表示针对特定服务进行的预订的数据,其中包含许多变量.

不久之前,我遇到了当前数据结构的问题,因此对预订的任何影响时间,日期或价格的更改都会影响其他相关财务记录,日期预订列表等.

我当时的解决方案是创建一个修改表来跟踪对预订所做的任何更改.然后,每当要求预订模型返回预订时,它将添加修改(在afterFind()蛋糕回调中)并提供最新版本的预订,如下所示(借用Paint绘图):

在此输入图像描述

当您要求预订模式返回预订#1234时,此方法可以正常工作.它返回最新的预订表示,包括所有修改(彼此叠加),包括包含所有修改的数组原始预订数据以供参考.

我的问题是我最近意识到我需要能够使用自定义条件查询此模型,并且如果其中一个条件在其中一个修改中实现,则结果将不匹配,因为模型正在搜索原始模型记录而不是最终呈现的记录.我查询模型以返回abc蓝色(不是灰色)的行的示例:

在此输入图像描述

在该示例中,模型直接查看原始数据,其中行为abc蓝色并且不返回此结果,因为蓝色值位于在找到原始结果附加的修改中.

我现在所做的是查询beforeFind()Booking模型的回调以查找符合给定条件的修改,加入预订以确保任何其他条件仍然匹配.当它在上面的例子中返回蓝色时,它将结果作为类属性存储在数组中,并继续使用常规find(),但不包括退回该预订的ID(因为我们发现了更新的最新版本) ).然后它将它们合并在一起,再次将它们排序等afterFind().

这是有效的,虽然我希望它有点啰嗦.

毕竟,我已经意识到在这个应用程序的其他部分,有些模型可以手动加入预订表并搜索预订.所以现在我需要一种方法能够将所有这些手动连接中的修改直接合并到MySQL中的表中,而不会影响原始数据,最好不要更改我的代码.

我的想法是我需要删除手动连接并创建模型关联.请问beforeFind()afterFind()我说查询客户模型的hasMany预订(将修改应用到每个预订)其预订模式仍运行?

我的另一个选择是通过删除修改中可能包含的任何条件从MySQL返回更多行,然后使用PHP根据我的搜索条件过滤结果.这个选项让我感到有些害怕,因为如果没有这个标准,结果集可能会很大......


我该如何实现这种数据结构?我的关键要求仍然是我不想更改原始的预订记录,而是在顶部添加修改记录,但我需要能够通过模型查询预订(包括修改).

我想尝试在幕后尽可能多地保持这种集成,所以我不必通过我的整个应用程序来改变n看起来像这样的查询数量:

$get_blue = $this->Booking->find('all', array(
    'conditions' => array(
        'Booking.abc' => 'blue'
    )
));
Run Code Online (Sandbox Code Playgroud)

我希望能够隐含地包括对预订的任何修改,以便在上述查询中返回最新的预订.

另一个问题是当预订模型手动加入搜索查询时,如下所示:

$get_transactions_on_blue_bookings = $this->Transaction->find('all', array(
    'joins' => array(
        array(
            'table' => 'sql_bookings_table', // non-standard Cake format, I know - it's an example
            'alias' => 'Booking',
            'type' => 'LEFT',
            'conditions' => 'Booking.booking_id = Transaction.booking_id'
        )
    ),
    'conditions' => array(
        'Booking.abc' => 'blue'
    )
));
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,上面的查询将不包括在我的MSPAINT例如上述变形,因为它是手动加入表中的SQL(修改整合是在beforeafterFind()以预订模式的回调函数).

任何有关这方面的帮助将不胜感激.

编辑

我知道这已经足够长了,但我想我补充一点,我想跟踪这些变化并且不更新原始记录的原因是财务方面不能改变,因为它会影响报告.

到目前为止,我能看到的最快捷,最简单的解决方案是在所有情况下直接对原始预订进行修改,除非它影响财务信息,这仍然作为修改进行跟踪(因为我目前不需要根据此信息进行搜索) ).

Jos*_*ber 5

听起来你正在尝试实现一个时间数据库.时态支持是ANSI/ISO SQL:2011标准的主要补充之一.MySQL(像大多数RDBMS一样)落后于标准.将时态数据库视为CVS/SVN/Git的DBMS等价物.

相比之下,我们使用的没有时间特征的传统数据库可以称为当前数据库.

当前数据库中,如果您尝试实现时态支持,则可以通过多种方法使用不同方法失败:

  • 一桌式方法.当您需要进行修改时,您UPDATEs将对原始记录执行操作,除非您拥有某种自行开发的触发器/审计逻辑,否则不会显示历史记录.即使您有审计/更改日志,您也必须进行一些丑陋的挖掘以重建更改历史记录.

  • 双表方法.您可以将数据拆分为两个表,一个包含基本/原始记录(例如预订),另一个表用于更改/修改/增量,而不是就地进行修改.那么至少你保留了原始数据,但是你必须再次编写复杂的逻辑来查看原始数据并进行分层修改.如果您只想要应用一些修改,情况会变得更糟.

  • 预先计算的结果表方法.您保留3个或更多表:基本记录,修改,以及尝试始终具有结果的表(保持最新的基数+修改).祝你好运写触发器和过程,当你做这样的计算INSERTs,天上帮助你,如果一个UPDATEDELETE需要.该设置很脆弱,可能会失去同步,例如死锁和回滚.如果你没有在具有触发器/过程的数据库中执行此操作,则可以尝试在应用程序代码中实现结果计算,但是运气好 - 并且它可能会因多线程消费者而变得丑陋.而且,只使用了一些修改,您无法轻松访问结果.

结论:如果您不仅限于MySQL,您应该考虑使用具有内置临时支持的数据库.否则,你将重新实施轮子.