MySQL:从另一个表中的值“修补”表上的现有数据
Posted
技术标签:
【中文标题】MySQL:从另一个表中的值“修补”表上的现有数据【英文标题】:MySQL: "Patch" existing data on a table from values in another table 【发布时间】:2021-03-22 22:01:30 【问题描述】:我有两张表,结构相同。第一个填充有从另一个系统获得的可能需要更正的记录(可能是一个或多个列)。第二个表是我想应用于第一个表的更正。
例如,我可以在 table1 上有以下行:
order_number | name | email | tracking_no
101 null foo@bar.com 3456789
102 An Example ex@ample.com 1010101
...以及我想对 table2 上的这些行应用的更正:
order_number | name | email | tracking_no
101 Name Surname null null
102 null null 45778901
本质上:将缺少的name
添加到order_number
101 并更正错误的tracking_no
为order_number
102。
我正在尝试做的逻辑是:table1 中的“补丁”值与 table2 中相同的 order_number
包含的更正,优先于 table2 中的值,如果相应的不覆盖 table1 中的现有值table2 中的值为空。
对于 table1 中的值为 null 并且我们在 table2 中进行非 null 更正的情况,COALESCE
似乎是正确的方法,但我不知道如何用表 2 中相应的“修复”。
在 mysql/MariaDB 中是否有一种机制可以让我这样做,因为替代方案是一个非常混乱的“从两个表中提取两条记录,比较值并建立新的正确记录并将其插入回 table1”。
正如 cmets 中所指出的,这里有一组可重现的测试数据以及表结构:
USE so_demo;
DROP TABLE IF EXISTS so_demo.table1;
DROP TABLE IF EXISTS so_demo.table2;
CREATE TABLE so_demo.table1 (
order_number int(11) NOT NULL AUTO_INCREMENT,
name varchar(50) DEFAULT NULL,
email varchar(250) DEFAULT NULL,
tracking_no varchar(255) DEFAULT NULL,
PRIMARY KEY (order_number),
UNIQUE INDEX UK_table1_order_number (order_number)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci;
CREATE TABLE so_demo.table2 (
order_number int(11) NOT NULL AUTO_INCREMENT,
name varchar(50) DEFAULT NULL,
email varchar(250) DEFAULT NULL,
tracking_no varchar(255) DEFAULT NULL,
PRIMARY KEY (order_number),
UNIQUE INDEX UK_table2_order_number (order_number)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci;
INSERT INTO so_demo.table1 VALUES (101, NULL, "foo@bar.com", 3456789);
INSERT INTO so_demo.table1 VALUES (102, "An Example", "ex@ample.com", 1010101);
INSERT INTO so_demo.table2 VALUES (101, "Name Surname", NULL, NULL);
INSERT INTO so_demo.table2 VALUES (102, NULL, NULL, 45778901);
【问题讨论】:
你的表1上是否有索引 @P.Salmon 是的,order_number 是唯一索引。 见:Why should I provide an MCRE for what seems to me to be a very simple SQL query? @Strawberry 很公平,在问题上添加了结构和测试数据 您能否编辑以显示更新后所需的实际结果 【参考方案1】:您要查找的术语是合并,在 mysql 中插入重复键
drop table if exists t,t1;
create table t(order_number int primary key, name varchar(20) , email varchar(20), tracking_no int);
insert into t values
(101 , null , 'foo@bar.com' , 3456789),
(102 , 'An Example', 'ex@ample.com' , 1010101);
create table t1(order_number int, name varchar(20), email varchar(20), tracking_no int);
insert into t1 values
(101 , 'Name Surname', null , null),
(102 , null , null , '45778901');
insert into t
select * from t1
on duplicate key update
t.name = case when t1.name is not null then t1.name else t.name end,
t.email = case when t1.email is not null then t1.email else t.email end,
t.tracking_no = case when t1.tracking_no is not null then t1.tracking_no else t.tracking_no end
;
select * from t;
+--------------+--------------+--------------+-------------+
| order_number | name | email | tracking_no |
+--------------+--------------+--------------+-------------+
| 101 | Name Surname | foo@bar.com | 3456789 |
| 102 | An Example | ex@ample.com | 45778901 |
+--------------+--------------+--------------+-------------+
2 rows in set (0.001 sec)
【讨论】:
t.name=Coalesce(t1.name, t.name) :) 这就是我想要实现的目标,谢谢@P.Salmon!进一步的查询:我不介意只复制 case 语句,但我正在处理的实际表有大约 50 列。是否有将相同的 case 语句应用于所有列的简写?谢谢。 恐怕不会 - 尽管正如已经指出的那样,coalesce 不那么冗长。以上是关于MySQL:从另一个表中的值“修补”表上的现有数据的主要内容,如果未能解决你的问题,请参考以下文章