web-dev-qa-db-ja.com

MySQL LOAD DATA INFILE:動作しますが、予測できないラインターミネータ

MySQLには素敵なCSVインポート機能LOAD DATA INFILEがあります。

定期的にCSVからインポートする必要がある大きなデータセットがあるので、この機能はまさに私が必要としているものです。データを完全にインポートする実用的なスクリプトがあります。

.....例外....行末ターミネーターがどうなるかは事前にわかりません。

私のSQLコードは現在次のようになっています。

LOAD DATA INFILE '{fileName}'
 INTO TABLE {importTable}
 FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
 LINES TERMINATED BY '\n'
 IGNORE 1 LINES
( {fieldList} );

これは、一部のインポートファイルに最適です。

ただし、インポートデータは複数のソースから取得されています。それらのいくつかは\nターミネーターを持っています。他の人は\r\nを持っています。どれを持っているか予測できません。

LOAD DATA INFILEを使用して、行が\nまたは\r\nで終了するように指定する方法はありますか?どうすればこれに対処できますか?

16
SDC

前処理するだけです。インポートプロセスの一部としてコマンドラインツールから\ r\nを\ nに変更するためのグローバル検索/置換は、シンプルでパフォーマンスが高い必要があります。

10
codemonkey

行区切り文字を「\ n」として指定し、必要に応じて、ロード中に最後のフィールドから末尾の「\ r」区切り文字を削除できます。

例えば ​​-

'entries.txt'ファイルがあるとします。行区切り文字は '\ r\n'であり、行ITEM2 | CLASS3 | DATE2の後にのみ区切り文字は '\ n'です。

COL1  | COL2   | COL3
ITEM1 | CLASS1 | DATE1
ITEM2 | CLASS3 | DATE2
ITEM3 | CLASS1 | DATE3
ITEM4 | CLASS2 | DATE4

CREATE TABLEステートメント:

CREATE TABLE entries(
  column1 VARCHAR(255) DEFAULT NULL,
  column2 VARCHAR(255) DEFAULT NULL,
  column3 VARCHAR(255) DEFAULT NULL
)

LOAD DATA INFILEクエリ:

LOAD DATA INFILE 'entries.txt' INTO TABLE entries
FIELDS TERMINATED BY '|'
LINES TERMINATED BY '\n'
IGNORE 1 LINES
(column1, column2, @var)
SET column3 = TRIM(TRAILING '\r' FROM @var);

結果を示す:

SELECT * FROM entries;
+---------+----------+---------+
| column1 | column2  | column3 |
+---------+----------+---------+
| ITEM1   |  CLASS1  |  DATE1  |
| ITEM2   |  CLASS3  |  DATE2  |
| ITEM3   |  CLASS1  |  DATE3  |
| ITEM4   |  CLASS2  |  DATE4  |
+---------+----------+---------+
11
Devart

私はあなたがどのプログラミング言語によってもmysqlnoを通してのみ情報を必要とすると仮定します。使用する前に、データをロードしてフォーマットをwindows format\r\n(CR LF =)メモ帳++がある場合。次に、データの読み込みクエリを処理します。行が '\ r\n'で終了していることを確認します。

enter image description here

編集:

エディターは大きなファイルの変換には適さないことが多いためです。大きなファイルの場合、次のコマンドがWindowsとLinuxの両方でよく使用されます

1)WindowsでWindows形式に変換するには

TYPE [unix_file] | FIND "" /V > dos_file

2)LinuxでWindows形式に変換するには

unix2dos  [file]

他のコマンドも利用可能

Windows形式のファイルは、すべてのASCIICR\r文字をtr -dで削除するだけで、Unix形式に変換できます。 '\ r' <入力ファイル>出力ファイル

grep -PL $'\r\n' myfile.txt # show UNIX format  style file (LF terminated)
grep -Pl $'\r\n' myfile.txt # show WINDOS format style file (CRLF terminated)

Linux/unixでは、fileコマンドは、使用されているEnd-Of-Line(EOL)のタイプを検出します。したがって、このコマンドを使用してファイルタイプを確認できます

3
Prathap

最初に、線がどのように終わるかを覗いてみませんか?

$handle = fopen('inputFile.csv', 'r');

$i = 0;
if ($handle) {
    while (($buffer = fgets($handle)) !== false) {

        $s =  substr($buffer,-50);

        echo $s; 
        echo preg_match('/\r/', $s) ? 'cr ' : '-- ';
        echo preg_match('/\n/', $s) ? 'nl<br>' : '--<br>';          

        if( $i++ > 5)
            break;

    }

    fclose($handle);
}
1
Tim

また、そこにあるデータ統合パッケージの1つを調べることもできます。 Talend Open Studioには、非常に柔軟なデータ入力ルーチンがあります。たとえば、1セットの区切り文字を使用してファイルを処理し、拒否をキャッチして別の方法で処理することができます。

1
BRM

最初のロードに0行がある場合は、他の行ターミネーターで同じステートメントを実行します。これは、いくつかの基本的なカウントロジックで実行できるはずです。

少なくともそれはすべてSQLにとどまり、最初に勝ったときに機能する場合は。また、すべての行を再スキャンして特定の文字を削除するよりも頭痛の種が少なくなる可能性があります。

1
Breland

LINES STARTINGを使用して、テキストと新しい行の通常の行末を区切ることができます。

LOAD DATA LOCAL INFILE '/home/laptop/Downloads/field3-utf8.csv' 
IGNORE INTO TABLE Field FIELDS 
TERMINATED BY ';' 
OPTIONALLY ENCLOSED BY '^' 
LINES STARTING BY '^' 
TERMINATED BY '\r\n' 
(Id, Form_id, Name, Value)

文字を囲む「

...
LINES STARTING BY '"' 
...
0
Ivan Abramenko