需要一些想法来在任何给定的时间点恢复表的内容

Posted

技术标签:

【中文标题】需要一些想法来在任何给定的时间点恢复表的内容【英文标题】:Need some ideas with restoring a table's content in any given point in time 【发布时间】:2021-02-19 17:31:09 【问题描述】:

我有一个类似于以下的表结构:

CREATE TABLE Customer_Subscription
(
Customer_ID           INT
, Product_ID          INT
, Subscription_START  DATETIME
, Subscription_END    DATETIME
, PRIMARY KEY (Customer_ID, Product_ID)
)

然后,我还有一个审计表,如下所示:

CREATE TABLE Customer_Subscription_Audit
(
Audit_Code             CHAR(1)
, AuditCreatedDateTime DATETIME
, Customer_ID          INT
, Product_ID           INT
, Subscription_START   DATETIME
, Subscription_END     DATETIME
)

每当对表 Customer_Subscription 进行更改时,我都有一个触发器,该触发器还会向 Audit 表写入一行,记录之前被更改的值(未修改的版本),其中 INSERT UPDATE DELETE 由 Audit_Code 表示我','U','D'

我有一个问题,我希望能够使用我的 Customer_Subscription_Audit 表在过去的任何给定时间点重新创建我的 Customer_Subscription 表中的内容,我想知道最好的方法是什么?

(只是为了让它工作,我目前正在考虑逐行遍历审计表......我知道 RBAR 很糟糕......但它应该可以完成工作......但我想看看是否有更有效的方式也是如此)

【问题讨论】:

我认为你应该改变你的逻辑。首先,在插入中没有“先前”值。因此,插入行包含当前状态。这与为更新记录的行非常不同。你的逻辑与自己竞争。如果您的插入行包含当前值,那么您的其他操作也应该这样做。为什么?因为对于任何修改,前一行都包含 当前 更改的前图像。 IOW,只需记录任何操作的当前值。 对于删除,给定行的值实际上并没有改变。您只是记录了一行被删除的事实,而您真正需要的只是 PK 值和删除标志。如前所述,请仔细考虑在给定日期和时间您打算如何解释此信息。您应该生成一些精心规划的测试数据和用例,以真正了解您应该使用什么逻辑。 【参考方案1】:

审计表在修改前备份每行的状态。您可以使用窗口函数来实现逻辑:

select customer_id, product_id, subscription_start, subscription_end
from (
    select csa.*,
        row_number() over(
            partition by customer_id, product_id
            order by auditcreateddatetime
        ) rn
    from customer_subscription_audit csa
    where auditcreateddatetime >= @targetdatetime
) csa
where rn = 1 and audit_code <> 'I'

基本上,逻辑是过滤比恢复点更新的审计行,并为每个客户/产品元组选择最早的记录。插入事件应该被忽略。

【讨论】:

两个问题。如果 (cust id 1, prod id 1) 的行在 2020 年 11 月 1 日被删除,并且您的目标日期是 2020 年 11 月 2 日,那么您的结果集应该包含 (1, 1) 什么? @SMor:在我看来,它不应该出现在结果集中——这就是查询的作用。下一个事件是插入,我们将其过滤掉。 谢谢@GMB!我现在要试试这个,只是另一个琐事,审计表直到 2015 年左右才开始实施,所以有可能 Customer_Subscription 表中的一些记录,在 2015 年到现在之间没有被触及,不会有任何审计记录,在这种情况下,我想从我当前的表中获取值,如果审计表中没有匹配项,你认为它会起作用吗?

以上是关于需要一些想法来在任何给定的时间点恢复表的内容的主要内容,如果未能解决你的问题,请参考以下文章

php获取邮政编码的第一部分

将坐标转换为另一个坐标系

计算给定2点,纬度和经度的距离[重复]

算法:计算单词列表频率的更好方法

好的密码恢复方法

灵活序列化的任何想法