【问题标题】:Trying to do LOAD DATA INFILE with REPLACE and AUTO_INCREMENT尝试使用 REPLACE 和 AUTO_INCREMENT 执行 LOAD DATA INFILE
【发布时间】:2012-06-03 19:17:28
【问题描述】:

我正在尝试将文件加载到 MySQL 数据库中,主键为 auto_incremented,如果我发现任何重复的行,我希望更新数据。但是,REPLACE 关键字仅适用于主键,它是自动生成的,所以我被卡住了。

如何能够拥有一个 ID 为 auto_increments 的表,同时能够使用 LOAD DATA INFILE 从文件中插入/更新数据?

这是桌子

CREATE TABLE  `oxygen_domain`.`TEST` (
`TEST_ID` int(11) NOT NULL AUTO_INCREMENT,
`NAME` varchar(255) NOT NULL,
`VALUE` varchar(255) DEFAULT NULL,
PRIMARY KEY (`TEST_ID`,`NAME`,`VALUE`)
) 

这是命令

LOAD DATA LOCAL INFILE 'C:/testData.txt'
REPLACE
INTO TABLE TEST
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES
(NAME, VALUE);

这是样本数据

ignored name, ignored value
name1,value1
name2,value2
name3,value3

使用上述数据多次运行上述命令后想要的结果是

|TEST_ID |NAME |VALUE|
1, 'name1', 'value1'
2, 'name2', 'value2'
3, 'name3', 'value3'

【问题讨论】:

    标签: mysql replace auto-increment load-data-infile


    【解决方案1】:

    观察 #1

    你不应该做REPLACE,因为它是机械的DELETEINSERT

    正如MySQL Documentation 所说的替换

    第 2 段

    REPLACE 是对 SQL 标准的 MySQL 扩展。它要么插入,要么删除和插入。有关标准 SQL 的另一个 MySQL 扩展(插入或更新),请参阅第 13.2.5.3 节,“INSERT ... ON DUPLICATE KEY UPDATE 语法”。

    第 5 段

    要使用 REPLACE,您必须同时拥有该表的 INSERT 和 DELETE 权限。

    使用 REPLACE 将丢弃无法自动重用的 TEST_ID 已建立的值。

    观察 #2

    表格布局将不支持捕获重复键

    如果名字是唯一的,表格应该这样布局

    布局#1

    CREATE TABLE  `oxygen_domain`.`TEST` (
    `TEST_ID` int(11) NOT NULL AUTO_INCREMENT,
    `NAME` varchar(255) NOT NULL,
    `VALUE` varchar(255) DEFAULT NULL,
    PRIMARY KEY (`TEST_ID`),
    KEY (`NAME`)
    ) 
    

    如果一个名称允许多个值,表格应该这样布局

    布局#2

    CREATE TABLE  `oxygen_domain`.`TEST` (
    `TEST_ID` int(11) NOT NULL AUTO_INCREMENT,
    `NAME` varchar(255) NOT NULL,
    `VALUE` varchar(255) DEFAULT NULL,
    PRIMARY KEY (`TEST_ID`),
    KEY (`NAME`,`VALUE`)
    ) 
    

    建议的解决方案

    使用临时表来捕获所有内容。然后,根据布局从临时表中执行大 INSERT

    布局#1

    VALUE 替换为重复的NAME

    USE oxygen_domain
    DROP TABLE IF EXISTS `TESTLOAD`;
    
    CREATE TABLE `TESTLOAD` SELECT NAME,VALUE FROM TEST WHERE 1=2;
    
    LOAD DATA LOCAL INFILE 'C:/testData.txt'
    INTO TABLE `TESTLOAD`
    FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
    LINES TERMINATED BY '\r\n'
    IGNORE 1 LINES
    (NAME, VALUE);
    
    INSERT INTO `TEST` (NAME, VALUE)
    SELECT NAME, VALUE FROM `TESTLOAD`
    ON DUPLICATE KEY UPDATE VALUE = VALUES(VALUE);
    
    DROP TABLE `TESTLOAD`;
    

    布局#2

    忽略重复的(NAME,VALUE)

    USE oxygen_domain
    DROP TABLE IF EXISTS `TESTLOAD`;
    
    CREATE TABLE `TESTLOAD` SELECT NAME,VALUE FROM TEST WHERE 1=2;
    
    LOAD DATA LOCAL INFILE 'C:/testData.txt'
    INTO TABLE `TESTLOAD`
    FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
    LINES TERMINATED BY '\r\n'
    IGNORE 1 LINES
    (NAME, VALUE);
    
    INSERT IGNORE INTO `TEST` (NAME, VALUE)
    SELECT NAME, VALUE FROM `TESTLOAD`;
    
    DROP TABLE `TESTLOAD`;
    

    更新

    如果我们需要避免每次创建和删除表。我们可以在使用 INSERT...INTO 语句之前或之后 TRUNCATE TRUNCATE 表。因此,我们下次不必创建表了。

    【讨论】:

    • 是的,我在赏金后大约 10 分钟找到了答案。感谢您提供更好的答案。
    • 效果很好
    【解决方案2】:

    在 NAME & VALUE 上创建唯一索引并使用 IGNORE 而不是 REPLACE:

    LOAD DATA LOCAL INFILE 'C:/testData.txt'
    IGNORE
    INTO TABLE `TEST`
    FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
    LINES TERMINATED BY '\r\n'
    IGNORE 1 LINES
    (NAME, VALUE);
    

    【讨论】:

      【解决方案3】:

      只需从 LOAD DATA 中删除 REPLACE,执行两次即可得到想要的结果:

      LOAD DATA LOCAL INFILE 'C:/testData.txt'
      INTO TABLE TEST
      FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
      LINES TERMINATED BY '\r\n'
      IGNORE 1 LINES
      (NAME, VALUE);
      

      我想你并不是真的想要你发布的想要的结果,是吗?

      【讨论】:

        猜你喜欢
        • 2014-01-25
        • 2018-04-20
        • 1970-01-01
        • 2016-04-29
        • 2012-09-02
        • 2018-03-16
        • 1970-01-01
        • 2019-01-11
        • 1970-01-01
        相关资源
        最近更新 更多