web-dev-qa-db-ja.com

REPLACEとAUTO_INCREMENTを使用してLOADDATAINFILEを実行しようとしています

主キーがauto_incrementedであるMySQLデータベースにファイルをロードしようとしていますが、重複する行が見つかった場合はデータを更新したいと思います。ただし、REPLACEキーワードは、自動生成される主キーでのみ機能するため、行き詰まります。

auto_incrementsするIDを持つテーブルを作成すると同時に、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'
16
jonasMcFerreira

観察#1

REPLACEは機械的なDELETEおよびINSERTであるため、実行しないでください。

MySQL Documentation がREPLACEについて述べているように

パラグラフ2

REPLACEは、SQL標準のMySQL拡張機能です。挿入するか、削除して挿入します。標準SQLに対する別のMySQL拡張機能(挿入または更新)については、13.2.5.3項「INSERT ... ON DUPLICATEKEYUPDATE構文」を参照してください。

パラグラフ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 [〜#〜] できます。したがって、次回はテーブルを作成する必要はありません。

20
RolandoMySQLDBA

NAME&VALUEに一意のインデックスを作成し、REPLACEの代わりにIGNOREを使用します。

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);
0
MagyaDEV