【问题标题】:Stored procedure to copy only latest records from one table to another仅将最新记录从一个表复制到另一个表的存储过程
【发布时间】:2021-02-10 21:12:38
【问题描述】:

我的源表 TABLE_A 通过某些前端消费者应用程序每小时频繁更新。 我有另一个报表表 TABLE_B,它从 TABLE_A 中获取一些数据。

最初复制通过插入语句手动完成的记录。 现在这需要自动化,其中存储过程/脚本每 1 小时运行一次并复制记录。所以当这个脚本第二次运行时,它不应该复制它在第一次运行时已经复制的记录。 请帮助我如何做到这一点。

TABLE_A:

id  date         product    type
11  2020-10-14    abc        T
12  2020-10-16    def        P
- - - - - - - - - -- - - - -- - - - -- - - -- 
13  2020-10-17    ghi        K
14  2020-10-18    klm        L
15  2020-10-19    abc        T

TABLE_B

id        date              product       type
hadgha     2020-10-14         abc          T
gsggss     2020-10-16         def          P 

假设脚本在第一次运行时复制了前 2 条记录,之后记录 13/14/15 已添加到 TABLE_A。现在在第二次运行中,脚本应该将最后 3 条记录从 TABLE_A 复制到 TABLE_B..

【问题讨论】:

  • 为什么tableB 中的ids 与tableA 中的不同?
  • 什么定义了重复? idproduct/type?
  • 表A和表B的id不同,因为它们是完全独立的不同。我需要将几个字段从 tableA 拉到上面显示的 tableB 中。现在这样想 - 这是 10 月到 9 月,我用来获取的数据是通过我曾经使用 phpMyadmin 上传到表 B 中的 csv 文件。现在我必须上传 10 月份的数据,并从这个表 A 中转发所有未来几个月的数据。这个 tableA id 是 PK 和 auto_incremental。 tableB Id 字段与 dnot 增量不同。但是 TableB 有另一个字段 id_temp 是增量的。
  • 注意这个tableB id_temp 值和tableA id 值是不同的。就像一个以 1500 开头,另一个以 1 开头。但我愿意在 tableB 中添加任何列以获得解决方案。
  • 所以我在考虑存储过程的行,即有一个 temp_table 存储游标数据或类似的东西......我的思路可能完全错误,一个简单的查询可以做这个伎俩。

标签: mysql sql duplicates sql-insert


【解决方案1】:

假设id是两个表的主键,可以使用on duplicate key

insert into table_b values(id, date, product, type)
select id, date, product, type
from table_a
on duplicate key update id = values(id)

基本上这会尝试inserttable_atable_b 的所有内容;当满足已经存在的记录时,查询转到on duplicate key 子句,执行“虚拟”更新(值已经相同,所以这是一个无操作:MySQL 跳过更新)。

为了使其正常工作,我建议:

  • table_a 中的id 设置为int primary key auto_increment

  • table_b 中的id 设置为int primary key(不是自动递增,因为总是从另一个表中复制值)

【讨论】:

  • 在我的情况下,这将无法正常工作。我在解释为​​什么。为了实现您的解决方案,我在 table_b 中创建了一个名为 id_a 的列。这未设置为自动递增,因为值将从 tableA - 字段 id 复制。当前状态表 ID 日期产品类型 11 2020-10-14 abc T 12 2020-10-16 def P 13 2020-10-17 def P 14 2020-10-18 def P 15 2020-10-19 def P 16 2020 -10-20 分辨率 P
  • tableB id 日期产品类型 1a 2020-10-14 abc T 1b 2020-10-16 def P 要求的当前状态:到每隔一小时自动运行的脚本,该脚本从 id 13 复制 tableA 中的记录第一次运行到 16 ,下一次运行从 id 16 开始,后续运行也是如此。注意 tableA.id 和 tableB.id 是完全独立的,彼此没有任何关系。我也无法触摸/更改/更新 tableB 中的现有记录。
  • 解决方案/策略:我在 tableB 中添加了一个名为 id_a 的列。这将用于存储 tableA.id 值。 id date product type id_a 1a 2020-10-14 abc T 1b 2020-10-16 def P 现在我需要将记录 13/14/15/16 的值复制到表 B 中。所以我运行这个脚本 insert into ext_rev_payment values (id, date, product, type) select id, date, product, type from tableA WHERE id >= 13
  • 这将使 bt tableB 如下所示: id date product type id_a 1a 2020-10-14 abc T NULL/0 1b 2020-10-16 def P NULL/0 13 2020-10-17 def P 13 14 2020-10-18 def P 14 15 2020-10-19 def P 15 16 2020-10-20 def P 16 到目前为止一切顺利。
  • 现在新记录被添加到tableA:id date product type 11 2020-10-14 abc T 12 2020-10-16 def P 13 2020-10-17 def P 14 2020-10-18 def P 15 2020-10-19 def P 16 2020-10-20 def P 17 2020-10-20 def Y 18 2020-10-21 def Z 19 2020-10-21 def I
【解决方案2】:

我建议使用子查询将它们过滤掉,然后使用on duplicate key:

insert into table_b values(id, date, product, type)
    select id, date, product, type
    from table_a a
    where a.date = (select max(a2.date) from table_a a2 where a2.type = a.type and a2.product = a.product)
    on duplicate key update id = values(id);

这假设您对table_b(product, type) 有唯一的约束。

【讨论】:

    【解决方案3】:

    这些表没有任何重复的键或任何共同的约束。 正在创建的存储过程有变量来捕获最大计数 id,然后在每次运行时更新这个最大计数 id。这样​​可以确保它复制上次运行中没有复制的记录。

    【讨论】:

      猜你喜欢
      • 2010-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-16
      • 1970-01-01
      相关资源
      最近更新 更多