2016-11-09 25 views
0

我有一個Bash ETL過程,它接受一個CSV文件,修復它的格式(如果需要)並將內容加載到MariaDB數據庫中。我發現保存到數據庫的記錄少於文件中的記錄,我試圖理解爲什麼。作爲該過程的一部分,我將-vv添加到mysql命令中,以查看它正在執行的操作,並且輸出正在拋出我。不理解MySQL輸出LOAD DATA

我正在導入的文件有行(包括標題)。

我的命令:

out=$(mysql -h ${host} \ 
     -vv \ 
     -P ${port} \ 
     -u ${user} \ 
     -p"${password}" \ 
     --local-infile \ 
     my_table < ${scriptDir}/${target}.sql 2>&1) 

相關回應看起來像這樣(我加了換行):

LOAD DATA LOCAL INFILE '/tmp/mydata.csv' 
    REPLACE INTO TABLE my_table CHARACTER SET utf8 
    FIELDS TERMINATED BY ',' 
     OPTIONALLY ENCLOSED BY '"' 
    LINES TERMINATED BY '\n' 
    IGNORE 1 LINES 
    SET updated_at = NOW() 
-------------- 
Query OK, 410 rows affected, 1460 warnings 
Records: 365 Deleted: 45 Skipped: 0 Warnings: 1460 Bye 

這是第一次導入到表中。任何想法可能導致這條語句刪除45條記錄?

任何想法將不勝感激。

UPDATE

按照要求,這裏是表的定義:

CREATE TABLE `my_table` (
    `First Name` varchar(255) DEFAULT NULL, 
    `Last Name` varchar(255) DEFAULT NULL, 
    `Company` varchar(255) DEFAULT NULL, 
    `Email` varchar(255) DEFAULT NULL, 
    `Campaign Name` varchar(255) DEFAULT NULL, 
    `Event Date` date DEFAULT NULL, 
    `Live Views Duration` varchar(255) DEFAULT NULL, 
    `On Demand Views Duration` varchar(255) DEFAULT NULL, 
    `Job Title` varchar(255) DEFAULT NULL, 
    `Reg Date` varchar(255) DEFAULT NULL, 
    `Affiliate Data` varchar(255) DEFAULT NULL, 
    `Phone 1` varchar(255) DEFAULT NULL, 
    `City` varchar(255) DEFAULT NULL, 
    `State` varchar(255) DEFAULT NULL, 
    `Postal Code` varchar(255) DEFAULT NULL, 
    `Country` varchar(255) DEFAULT NULL, 
    `Industry` varchar(255) DEFAULT NULL, 
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `updated_at` datetime DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `uix_conversion` (`Email`,`Campaign Name`,`Event Date`), 
    KEY `ix_campaign_name` (`Campaign Name`) 
) ENGINE=InnoDB AUTO_INCREMENT=512 DEFAULT CHARSET=utf8; 

UPDATE

過了一段時間了,我已經刪除,沒有變化的唯一指標。我還將REPLACE查詢更改爲IGNORE查詢,現在跳過而不是刪除記錄。同樣的淨影響。而且,在多次測試同一個文件時,似乎缺少的記錄並不總是相同的缺失記錄。不知道這裏發生了什麼......

+0

您正在使用'REPLACE INTO'。你確定導入文件中沒有重複記錄嗎?雖然我從來沒有測試過,但我希望它們能夠被加載,然後再被替換。 –

+0

我的版本5.7.16使用'Duplicates:'在那裏,而不是'Deleted:'所以我不確定這是否可比。 –

+0

請提供表的「創建」? – Dekel

回答

1

documentation解釋它很清楚:

輸入行的REPLACEIGNORE關鍵字控制處理是唯一鍵值重複現有行:

  • 如果您指定REPLACE,則輸入行會替換現有的行。換句話說,對於主鍵或唯一索引具有與現有行相同的值的行。

如果你的表是空的,當你運行LOAD DATA INFILE命令,這意味着一些你從.csv文件導入的行包含了導入到表或的PK成一列重複值列上有一個UNIQUE INDEX

如果某行是要導入包含重複的PKUNIQUE INDEX列已導入行的值的值,則REPLACE關鍵字使已經導入行,以騰出空間給新的被刪除行(以不違反PRIMARYUNIQUE約束)。

更新了答案您發佈的表定義後:搜索在id列重複,也爲有在EmailCampaign NameEvent Date輸入.csv文件列在同一組值的行。

更新#2(業務方案的意見後): 如果.csv文件包含在列id不是空值,這些導入的值和idAUTO_INCREMENT財產不計。

您可以跳過從導入的id柱(並讓AUTO_INCREMENT完成它的工作)通過指定從.csv文件中的數據來設置列的列表:

LOAD DATA LOCAL INFILE '/tmp/mydata.csv' 
    REPLACE INTO TABLE my_table CHARACTER SET utf8 
    FIELDS TERMINATED BY ',' 
     OPTIONALLY ENCLOSED BY '"' 
    LINES TERMINATED BY '\n' 
    IGNORE 1 LINES 
    (`First Name`, `Last Name`, # put the rest of the column names here 
           # in the same order they are in the .csv file 
           # put a variable (like @a) to skip a column 
           # or to use the value in an expression in the SET clause 
    `Country`, `Industry`)  # but do not put `id` 
    SET updated_at = NOW() 

不列出現在列表中並且未在SET子句中設置的值將以其DEFAULT值(這是AUTO_INCREMENT被調用的id)設置。

+0

謝謝,但這是我的困惑的來源:'id'字段是一個自動增量。不應該重複,對吧?並且,在鍵入電子郵件時,數據庫缺少文件中存在的多個電子郵件地址。在REPLACE場景中,它應該至少存在一次......對嗎? –

+0

當且僅當您在查詢中沒有爲其提供值(或提供NULL)時,會自動生成'id'的值。 'LOAD DATA INFILE'查詢提供了一種方法來指定從文件加載哪些字段:將列的列表放置在「SET」子句之前的括號內。所有沒有出現在列表中並且沒有在'SET'子句中設置的字段將被設置爲其默認值(這是'id'的自動遞增值)。 – axiac

+0

對。我應該指定,文件中沒有標識並且沒有設置任何內容。這是一個唯一的標識符,只是爲了方便(我們有幾個自我加入的查詢)。實際上,我在運行導入之前刪除並重新添加它,因爲它僅在運行時使用_only_進行自我連接。 –