大量のCSVファイルをインポートするためにシェル組んだので残しておく
MySQL8.0 で実行
$ mysql --version
mysql Ver 8.0.11 for Linux on x86_64 (MySQL Community Server - GPL)
設定ファイルに以下を記述する必要があった
記述しないと 「 The used command is not allowed with this MySQL version 」って怒られる
[client]
loose-local-infile=1
もしかしたら以下も実行しとく必要があったかも
mysql> SET PERSIST local_infile= 1;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @@local_infile;
+----------------+
| @@local_infile |
+----------------+
| 1 |
+----------------+
1 row in set (0.00 sec)
mysql>
MySQL 8.0でLOAD DATA LOCAL INFILEが "ERROR 1148 (42000): The used command is not allowed with this MySQL version" で失敗する時
(参考にさせていただきました)
大量のCSVをインポートするシェル
実行ディレクトリにある ~.csv ファイルを全部読み込んでインポートします
#!/bin/bash
## INIT
PWD="PasSw0rd"
TOTAL=`ls *.csv | wc -l`
## テーブルクリア
echo 'TRUNCATE TABLE csv_table;' | MYSQL_PWD=$PWD mysql -u UserName DBName -s -N
## ディレクトリ内の CSV ファイルを対象にループ
ls `pwd`/*.csv | while read line
do
## CSV の行数取得
L=`cat "$line" | wc -l`
## カウンタ
cnt=`echo $(($cnt + 1))`
## 処理ファイル表示
echo "$line" | awk -v"cnt=$cnt" -v"total=$TOTAL" -v"line=$L" '{ printf("%3d/%3d %\0477d %s\n", cnt, total, line, $0);}'
## インポート処理
MYSQL_PWD=$PWD mysql -u UserName DBName << EOT
LOAD DATA LOCAL INFILE '$line'
INTO TABLE csv_table
FIELDS
TERMINATED BY ','
ENCLOSED BY '"'
LINES
TERMINATED BY '\r\n'
IGNORE 1 LINES;
EOT
done
## 結果行数表示
echo 'select count(*) from csv_table;' |
MYSQL_PWD=$PWD mysql -u UserName DBName -s -N |
awk '{printf("\nIMPORT %\047d Record\n", $0);}'
CSVファイルの先頭1行を読み飛ばしてます( IGNORE 1 LINES )
CSVはカンマ区切り( TERMINATED BY ',' )
CSVはダブルクォーテーションで囲まれてる( ENCLOSED BY '"' )
CSVの行の終わりは改行 ( TERMINATED BY '\r\n' )
CSV ファイルはUTF8 で作ってありました
実行時には以下のような表示を行います
1/128 56 /path/file1.csv
・・・・・
128/128 9,440 /path/file128.csv
IMPORT 201,289 Record
インポートしたデータのカラム毎のデータバリエーション数とレコード数確認
CSVにデータがあったのか、カラム毎にとりあえず確認してみる
#!/bin/bash
## INIT
PWD="PasSw0rd"
echo "desc csv_table;" |
MYSQL_PWD=$PWD mysql -u UserName DBName -s -N |
awk '{print $1;}' |
while read line
do
col=$(echo $line | sed -e 's/\//_/g')
echo "$line" | awk '{printf("SELECT `%s`, count(*) FROM csv_table GROUP BY `%s` ORDER BY 2 DESC, 1\n", $1, $1);}' |
MYSQL_PWD=$PWD mysql -u UserName DBName -s -N > "lst.$col"
cnt=`cat "lst.$col" | wc -l`
if [ $cnt -ne 1 ]
then
echo "$line" | awk -v"cnt=$cnt" '{printf("%\0477d %s\n", cnt, $0);}'
if [ $cnt -lt 10 ]
then
cat "lst.$col" | awk '{printf(" : %s\n", $0);}'
fi
fi
done
カラム内のデータバリエーションがない場合は表示対象外にして( if [ \$cnt -ne 1 ] )
バリエーションが少ない場合はデータ内容毎のレコード数を表示してみる( if [ \$cnt -lt 10 ] )
実行結果はこんな感じ
109,790 xxキー
40,927 xx番号
46,699 xx名
21,118 xxxx
14 xxxxxx
223 xxx
2 xx種別
: 201051
: 001 238
4,862 xxxxxxxxx
・・・・・
xxキー は 109,790のバリエーションがあり
xx種別 は 2 バリエーションあり、内容は 空白が 201,051レコード、種別 001 が 238レコード
のような表示になります