2

这是一个仅供讨论的问题。现在,我需要重新设计一个mysql数据库表。基本上,该表包含我从另一个数据库同步的所有合同记录。合同记录可以修改、删除或用户可以通过GUI界面添加新的合同记录。在这个阶段,表结构与合同信息完全相同(列:序列号、到期日等)。在这种情况下,我只能同步整个表(删除所有旧记录,替换为新记录)。如果我想增量(仅与修改、新、删除的记录同步)同步表,我应该如何更改数据库架构?

这是我想出的方法,但我需要您的建议,因为我认为这是数据库应用程序中的常见场景。1)引入序号概念/列:对于每一个序号,用这个序号标记新增加的记录、修改的记录、删除的记录。通过记录最后同步的序号,只传递序号较高的记录;

2)因为删除的合约可以重新添加,并且原表有主键约束,我应该为那些删除的记录创建另一个表吗?或添加一个标志列以指示该合同是否已被删除?

我希望我能清楚地解释我的问题。无论如何,如果您对此有任何文章或您自己的建议,请告诉我。谢谢!

4

1 回答 1

9

我认为您对增量的概念感到困惑。

您要么收到全部负载(整个数据集),要么只收到更改(“增量”)。

如果你处理满载,你可以做一个截断+插入。这样您就不必处理新旧行或删除。由于参照完整性约束等原因,这可能不可行。

如果您收到 delta,则每行通常会被放入 2 个类别中的 1 个类别中:

  1. 匹配键 = UPDATE。您可以选择忽略具有相同数据的行或覆盖。
  2. 没有匹配的键 =INSERT

删除是特殊的。不存在的行无法发送给您。因此,您需要就如何处理它达成一致。在满载的情况下,可以删除接收到的数据集中不存在的所有本地行。

如果是 delta,您可以同意发送带有删除标记(标志、日期)的行。然后,您可以决定是否使用删除标记(由上面的 (1) 自动处理)保留该行,或者是否应该保留该DELETE行。我建议保留它,因为迟早有人会指责您缺少行/数据质量差,然后您将 DELETE_DATE 扔在他们的脸上。

对于 MySQL,您可以使用INSERT ... ON DUPLICATE KEY UPDATE来实现“upsert”功能。

如果您需要更具体的帮助,则必须提供更多详细信息。

更新:

好的,这是一个例子。假设您有以下表结构:

create table contracts(
   contract_id int         not null
  ,details1    varchar(20)
  ,details2    varchar(20)
  ,delete_date date
  ,primary key(contract_id)
);

每当您收到更新的行时,将它们插入到具有相同结构的临时表中:

create table contracts_delta(
   contract_id int         not null
  ,details1    varchar(20)
  ,details2    varchar(20)
  ,delete_date date
  ,primary key(contract_id)
);

一些示例数据:

mysql> select * from contracts;
+-------------+----------+----------+-------------+
| contract_id | details1 | details2 | delete_date |
+-------------+----------+----------+-------------+
|           1 | a1       | a2       | NULL        |
|           2 | b1       | b2       | NULL        |
|           3 | c1       | c2       | 2011-01-03  |
+-------------+----------+----------+-------------+

mysql> select * from contracts_delta;
+-------------+----------+----------+-------------+
| contract_id | details1 | details2 | delete_date |
+-------------+----------+----------+-------------+
|           2 | b1       | b2       | 2011-01-03  | <-- Row was deleted
|           3 | c1       | c2       | NULL        | <-- No longer deleted
|           4 | d1       | d2       | NULL        | <-- This is new row
+-------------+----------+----------+-------------+

使用我之前链接的语法,您可以插入所有新行。每当行已经存在(重复)时,我们选择更新列。请注意,这会自动处理已删除的行,因为 delete_date 与其他所有内容一样是常规列。

insert 
  into contracts(
        contract_id
       ,details1
       ,details2
       ,delete_date
       )
 select contract_id
       ,details1
       ,details2
       ,delete_date
  from contracts_delta s
    on duplicate key 
    update contracts.details1    = s.details1
          ,contracts.details2    = s.details2
          ,contracts.delete_date = s.delete_date;

在“upsert”之后,合约中的数据将如下所示:

mysql> select * from contracts;
+-------------+----------+----------+-------------+
| contract_id | details1 | details2 | delete_date |
+-------------+----------+----------+-------------+
|           1 | a1       | a2       | NULL        |
|           2 | b1       | b2       | 2011-01-03  |
|           3 | c1       | c2       | NULL        |
|           4 | d1       | d2       | NULL        |
+-------------+----------+----------+-------------+

-- 此时可以选择删除delta表(下次记得重新创建)

drop table contracts_delta;

- 或者您可以截断它以节省一些空间。(无论如何,您需要确保它在下一次加载时是空的)

truncate table contracts_delta;

-- 或者您可以保存实际的增量(重命名表),以防您有时需要单独的增量

alter table contracts_delta rename to contracts_delta_20110115;
于 2011-01-13T22:32:21.173 回答