从表 2 更新表 1(插入新的,仅更新更改,删除丢失的)

Update table1 from table2 (Insert new, update changed only, remove missing)

我看到类似的问题问了十几次,但 none 完全符合我的情况。

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

  1. 删除缺失的 appids
  2. 新增appids
  3. 更新 name 如果它已经改变

此外,更新后还有 2 个触发器 (多亏了我才意识到我在做什么,而不仅仅是 运行 损坏的代码)

  1. 在历史记录中记录更新 table (table3)
  2. 在历史记录中记录删除 table (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;

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

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


编辑: 实际上,使用下面 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
    );

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

但是,您可以分两步执行操作:首先删除目标中的 "missing" 行,然后使用 insert ... on duplicate key 到 insert/update 新行和现有行:

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 定义为临时 table table2 的主键:这将使查询更快。