尝试使用REPLACE和AUTO_INCREMENT执行LOAD DATA INFILE

时间:2012-05-29 14:35:53

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

我正在尝试将文件加载到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'

3 个答案:

答案 0 :(得分:20)

观察#1

您不应该REPLACE,因为它是机械DELETEINSERT

正如MySQL Documentation所说的关于REPLACE

第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表。因此,我们下次不必创建表。

答案 1 :(得分:0)

在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);

答案 2 :(得分:-2)

只需从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);

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