从表 2 更新表 1(插入新的,仅更新更改,删除丢失的)
Update table1 from table2 (Insert new, update changed only, remove missing)
我看到类似的问题问了十几次,但 none 完全符合我的情况。
我的意图是根据 csv 导入的临时 table (table2) 更新当前 table (table1);
- 删除缺失的
appid
s
- 新增
appid
s
- 更新
name
如果它已经改变
此外,更新后还有 2 个触发器 (多亏了我才意识到我在做什么,而不仅仅是 运行 损坏的代码);
- 在历史记录中记录更新 table (table3)
- 在历史记录中记录删除 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)
当然,这假定 id
是 table1
的主键(因此 insert
语句可以正确识别重复项)。我还建议将 id
定义为临时 table table2
的主键:这将使查询更快。
我看到类似的问题问了十几次,但 none 完全符合我的情况。
我的意图是根据 csv 导入的临时 table (table2) 更新当前 table (table1);
- 删除缺失的
appid
s - 新增
appid
s - 更新
name
如果它已经改变
此外,更新后还有 2 个触发器 (多亏了我才意识到我在做什么,而不仅仅是 运行 损坏的代码);
- 在历史记录中记录更新 table (table3)
- 在历史记录中记录删除 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)
当然,这假定 id
是 table1
的主键(因此 insert
语句可以正确识别重复项)。我还建议将 id
定义为临时 table table2
的主键:这将使查询更快。