2016-11-09 5 views
0

私は、CSVファイルを受け取り、そのフォーマットを修正し(必要に応じて)、コンテンツをMariaDBデータベースにロードするBash ETLプロセスを使用しています。私は、データベースに保存されたレコードがファイル内のレコードよりも少なく、その理由を理解しようとしていることがわかりました。そのプロセスの一環として、mysqlコマンドに-vvを追加して、それが何をしているかを確認し、出力が私を投げているのを確認します。MySQL LOAD DATAの出力を理解しない

インポートするファイルには、行(ヘッダーを含む)があります。

マイコマンド:

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 

これは、テーブルに最初のインポートです:

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

関連応答は、この(私は改行を追加しました)のように見えます。この声明で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は 'Deleted:'ではなく 'Duplicates:'を使用していますので、これが匹敵するかどうかはわかりません。 –

+0

テーブルの 'create'を提供してください? – Dekel

答えて

1

documentationはかなり明確にそれを説明していない:

ユニークキー値に存在する行を複製するインプット行のREPLACEIGNOREキーワード制御処理:

  • REPLACEを指定すると、入力行が既存の行を置き換えます。つまり、既存の行と同じプライマリキーまたはユニークインデックスの値を持つ行です。

あなたのテーブルが空の場合は、LOAD DATA INFILEコマンドを実行すると、それはあなたが.csvファイルからインポートした行のいくつかは、テーブルのPKに、またはにインポートされた列に重複する値が含まれていることを意味し列にはUNIQUE INDEXがあります。

輸入されようとしている行がPKまたはUNIQUE INDEX列にすでにインポート行の値が重複した値が含まれている場合は、REPLACEキーワードが既にインポート行は新しいのための部屋を作るために削除されるようになります(PRIMARYまたはUNIQUEの制約に違反しないように)。Emailに同じ値のセットを持つ行にもid列内の重複を検索して、Campaign Name、入力.csvファイルのEvent Date列:あなたがテーブル定義を掲示した後

は答えを更新しました。 (OPさんのコメントの後)

更新#2.csvファイルには、列idで、空でない値が含まれている場合、インポートされたそれらの値とid列のAUTO_INCREMENTプロパティはカウントされません。ない

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() 

列:

あなたは.csvファイルからのデータで設定される列のリストを指定して、インポートされることからid列をスキップ(とAUTO_INCREMENTはその仕事をやらせる)ことができますリストに表示され、SET句に設定されていない句は、の値で設定されます(idの場合はAUTO_INCREMENTが呼び出されます)。

+0

ありがとうございますが、私の混乱の原因はここにあります。「id」フィールドは自動インクリメントです。重複してはいけませんよね?また、電子メールにキーイングすると、ファイルに存在するいくつかの電子メールアドレスがデータベースに欠落しています。 'REPLACE'シナリオでは、少なくとも1回は存在するはずです...そうですか? –

+0

'id'の値は、クエリに値を指定しない(または' NULL'を指定する)場合にのみ、自動的に生成されます。 'LOAD DATA INFILE'クエリは、ファイルから読み込むフィールドを指定する方法を提供します。' SET'句の直前のカッコで列のリストを置きます。リストに存在せず、 'SET'節で設定されていないすべてのフィールドは、デフォルト値(' id'の自動インクリメント値)で設定されます。 – axiac

+0

右。私は指定する必要があります、ファイル内のIDがないと何も設定されていません。これは便宜のためのユニークな識別子です(私たちはいくつかの自己結合クエリを持っています)。実際、実行時に自己結合のために使用されるだけなので、インポートを実行する直前にドロップして再追加します。 –