php - 有效管理数据变更

标签 php mysql cakephp database-design cakephp-1.3

我有一张叫做 Bookings 的表。该表包含代表针对特定服务进行的预订的数据,其中包含许多变量。

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

我当时的解决方案是创建一个修改表,用于跟踪对预订所做的任何更改。然后,每当 Booking 模型被要求返回预订时,它都会添加修改(在 afterFind() Cake 回调中)并呈现预订的最新版本,类似这样(请原谅 Paint 绘图):

enter image description here

当您要求预订模型返回预订 #1234 时,此方法工作正常。它返回预订的最新表示,包括所有修改(相互叠加),包括一个包含所有修改的数组 原始预订数据以供引用。

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

enter image description here

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

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

这是有效的,尽管它比我希望的要冗长一些。

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

我的想法是我需要删除手动连接并创建模型关联。请问beforeFind()afterFind()当我查询说有许多预订的客户模型时,预订模型仍然运行(将修改应用于每个预订)?

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

我怎样才能实现这种数据结构?我的关键需求仍然是我不想改变原来的Booking记录,而是在上面添加Modification记录,但我需要能够通过模型查询预订(包括修改)。

我想尝试在幕后尽可能多地保留这种集成,这样我就不必遍历整个应用程序来更改 n如下所示的查询数量:

$get_blue = $this->Booking->find('all', array(
    'conditions' => array(
        'Booking.abc' => 'blue'
    )
));

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

另一个问题是当 Booking 模型手动加入搜索查询时,如下所示:
$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'
    )
));

如您所见,上面的查询不会包括我上面 MSPaint 示例中的修改,因为它是在 SQL 中手动加入表(修改集成在预订模型的 beforeafterFind() 回调函数中)。

对此的任何帮助将不胜感激。

编辑

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

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

最佳答案

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

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

当前数据库 ,如果您尝试实现时间支持,您可能会以多种方式失败,使用不同的方法:

  • 一 table 方法。 需要修改时,做UPDATEs在您的原始记录上,除非您有某种自行开发的触发/审计逻辑,否则历史记录是不存在的。即使您有审核/更改日志,您也必须进行一些丑陋的挖掘以重建更改历史记录。
  • 二表法。 您不是在原地进行修改,而是将数据拆分为两个表,一个包含基本/原始记录(例如预订),另一个包含您的更改/修改/增量。那么至少您保留了原始数据,但是您又必须编写复杂的逻辑来查看原始数据并进行分层修改。如果您只想应用一些修改,情况会更糟。
  • 预先计算的结果表方法 .您保留 3 个或更多表:基本记录、修改以及一个尝试始终具有结果的表(保持最新的基本 + 修改)。祝您在执行此计算时编写触发器和程序时好运 INSERTs , 和天堂帮助你如果 UPDATEDELETE需要。设置很脆弱,可能会不同步,例如死锁和回滚。如果您不使用触发器/过程在数据库中执行此操作,您可以尝试在应用程序代码中实现结果计算,但祝您好运 - 多线程消费者可能会变得丑陋。而且,您无法轻松访问仅应用一些修改的结果。

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

    关于php - 有效管理数据变更,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24297338/

    相关文章:

    php - 如何在 Zend view Helper 中访问 url 变量的值?

    php - 静态标准: Non-Static method Date utility

    php - 如何在php中按下提交按钮之前显示不同数量的记录

    mysql - 如何在mysql中返回json字符串的值

    php - CakePHP 2.0.5 表单输入日期时间语言

    如果字段重复,Php sql 只回显一行

    mysql - utf8 数据存储在数据库中时应该是什么样子?

    mysql - 在mysql中选择多个计数

    cakephp:如何使 NOW() 在搜索条件下工作?

    cakephp - 如何在nginx中配置cakephp