【问题标题】:Update table1 from table2 (Insert new, update changed only, remove missing)从 table2 更新 table1(插入新的,仅更新更改,删除缺失的)
【发布时间】:2020-09-24 14:58:46
【问题描述】:

我看到类似的问题被问了十几次,但都不是我的场景。

我的意图是根据 csv 导入的临时表 (table2) 更新当前表 (table1);

  1. 删除缺失的appids
  2. 添加新的appids
  3. 如果 name 已更改,请更新

另外还有一个更新后的触发器(感谢我意识到我在做什么而不是简单地使用损坏的代码运行);

  1. 在历史记录表 (table3) 中记录更新
  2. 在历史记录表 (table3) 中记录删除

目前我执行如下操作:

CREATE TEMPORARY TABLE table2 (
    appid INT,
    name VARCHAR(255)
    );
LOAD DATA LOCAL INFILE "outp.csv" INTO TABLE table2 
    FIELDS TERMINATED BY ','
    ENCLOSED BY '"'
    LINES TERMINATED BY '\n';

UPDATE table1
INNER JOIN table2 ON table2.appid = table1.appid
SET table1.name = table2.name;

DROP TEMPORARY TABLE table2;

目前,每当我运行更新时,历史记录表都会获取所有现有行,而且不会导入新行,也不会删除丢失的行。

完成预期更新操作的正确方法是什么?


编辑:实际上,使用下面 GMB 提供的确切陈述更有意义。在我意识到插入语句的工作原理之后,避免运行第三条不必要的语句会更有意义,因为插入将同时执行插入和更新。

旧三语句脚本供参考:

DELETE FROM table1
WHERE NOT EXISTS(
    SELECT 1
    FROM table2
    WHERE table2.appid = table1.appid
    );

UPDATE table1 INNER JOIN table2 ON table2.appid = table1.appid
SET table1.name = table2.name
WHERE table1.name <> table2.name;

INSERT INTO table1 (appid, name)(
    SELECT table2.appid, table2.name FROM table2
    LEFT JOIN table1 ON table2.appid = table1.appid
    WHERE table1.appid IS NULL
    );

【问题讨论】:

  • 你能简单地替换整个表吗?

标签: sql sql-update mariadb sql-insert load-data-infile


【解决方案1】:

您不能在一条语句中做到这一点。与其他一些数据库不同,MySQL/MariaDB 不提供功能齐全的merge 语句。

但是,您可以分两步执行操作:首先删除目标中的“缺失”行,然后使用insert ... on duplicate key 插入/更新新的和现有的行:

delete from table1 
where not exists(select 1 from table2 where table2.appid = table1.appid)

insert into table1 (appid, name)
select appid, name
from table2
on duplicate key update name = values(name)

当然,这假定idtable1 的主键(因此insert 语句可以正确识别重复项)。我还建议将id 定义为临时表table2 的主键:这将使查询更快。

【讨论】:

  • 是否可以定义 WHEN 语句与 'on duplicate' 以避免不必要的更新?如果没有,我找到了另一个关于插入和更新的声明,当我用最好的方法解决时,我会添加到原始帖子中。但删除语句似乎运行很长时间(30 分钟以上)。是否有可能以某种方式对其进行优化?
  • @ichihaifu:(1)表的总大小是多少,删除了多少行? (2)您是否按照建议将id定义为临时表的主键?
  • table1当前有96750行,appid为主键。在我的第一次测试运行中没有删除任何密钥,但那是因为(很可能)没有要删除的密钥。我可以删除一些来模拟删除案例。 -> 编辑:我还没有尝试在临时表中设置主键。
  • 啊哈,是的。指定主键后,运行删除只需要不到一秒钟的时间。谢谢。
  • @ichihaifu:没有。但是如果name的值相同,MySQL实际上并没有写。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多