首页 > 解决方案 > 如何在不替换整行的情况下从 CSV 更新表中的特定列?

问题描述

我有一组要导入 mysql 的 csv 文件,并且在对数据进行排序时犯了一些错误。我需要在不更新整个表的情况下对表中的特定行进行大规模更新(表发生了一些更改,重新导入所有内容将恢复更改)。

这是我用来导入 csv 文件的命令:

LOAD DATA LOW_PRIORITY LOCAL INFILE 'C:\\location\\of\\CSVs\\import.csv' 
REPLACE INTO TABLE `database`.`contacts` CHARACTER SET utf8 
FIELDS TERMINATED BY ',' 
OPTIONALLY ENCLOSED BY '"' 
LINES TERMINATED BY '\r\n' 
IGNORE 2 LINES 
(`id`, `deleted`, `salutation_name`, `first_name`, `last_name`, `account_id`, 
`description`, `created_at`, `modified_at`, `created_by_id`, 
`modified_by_id`, `assigned_user_id`);

我尝试使用 INSERT 代替 REPLACE:

LOAD DATA LOW_PRIORITY LOCAL INFILE 'C:\\location\\of\\CSVs\\import.csv' 
INSERT INTO TABLE `database`.`contacts` 
CHARACTER SET utf8 
FIELDS TERMINATED BY ',' 
OPTIONALLY ENCLOSED BY '"' 
LINES TERMINATED BY '\r\n' 
IGNORE 2 LINES 
(`id`, `created_by_id`, `assigned_user_id`);

但它抛出了错误(预期)并且没有更新任何东西!

基本上,我只想根据第一列从 csv 中导入两列created_by_idassigned_user_idid但我不完全确定如何在不替换表中所有内容的情况下做到这一点。

我很确定我需要 WHERE在某处声明来告诉mysql它的更改基于什么,但我不完全确定要放入什么/在哪里。

需要明确的是,我有点像 mysql 脚本小子(这是我的第一个数据库,也是我第一次涉足 mysql),但我很聪明,可以创建数据库备份并将表复制到临时表,然后再进行修补。

标签: mysql

解决方案


不幸的是,方便的语法LOAD DARA INFILE不支持REPLACE,或其他选项,例如ON DUPLICATE KEY UPDATE.

如果您的表是从 CVS 文件初始化的,我建议您只截断表并使用正确的命令重新加载 CSV。

另一方面,如果您不能截断表,那么另一种选择是将 CSV 文件加载到临时表中,然后从临时表中更新目标表。假设您在 temp table 中加载了文件tmp_contacts,并且主键是id,那么您的update语句将是:

update contacts c
inner join tmp_contacts t
    on t.id = c.id
set 
    c.created_by_id = t.created_by_id,
    c.assigned_user_id = t.assigned_user_id

如果您的表有很多列,则可以在加载临时表时跳过不需要的列。MySQL 文档解释了如何使用会话变量来做到这一点。


推荐阅读