空飛ぶチンアナゴの統計解析日記

統計解析を嗜むチンアナゴのメモ帳です

MySQL 8でcsvをインポートしたいというよくある話

ただし、コードはPythonを使って書くものとする。
いっぱいcsvファイルを読み込ませないといけなくて、いちいちコンソールでうつのがだるいのでなんとかしないとなーという問題を抱えているわけですよ。

コンソールで打ち込む場合の方法

qiita.com
yoku0825.blogspot.com
この辺りの記事にもある通り

  • --local-infile のデフォルトが0になったので明示的に1を指定してやる必要がある
  • mysqld, mysql コマンドラインクライアント それぞれ別に --local-infile オプションを持っているので、両方1に指定しないとダメ。

https://yoku0825.blogspot.com/2018/07/mysql-80load-data-local-infile-error.htmlより抜粋

ということでこの辺りのサイトを参考にすれば問題なくインポートはできました。

ということでこれをPythonでやりたい

単純に

import mysql.connector

cnn = mysql.connector.connect(
    user='username',
    pasword = 'pass',
    host = 'localhost',
    database = 'test_db'
)

curs = cnn.cursor()
sql = """
    LOAD DATA
         LOCAL
         INFILE "ファイルのpass"
         INTO TABLE table_test
"""
curs.execute(sql)

curs.commit()
curs.close()

とコードを書いてもエラーが出るので、何か工夫が必要になります。

1)コンソールの時のようにログイン時に設定をする

$mysql -u username -p --local_infile

でログインすれば問題なくできるように、mysql.connectorのconnect関数を設定すればいいのではなかろうかと試行錯誤。
で、実際の引数はこちらで確認できます。
dev.mysql.com
allow_local_infileが怪しそうなんだけど、デフォルト値がTrueなのでここをいじれば改善できるとはちょっと考えにくいことから別のアプローチが必要そうです。

2)my.cnfを変更する

taiga.hatenadiary.com
ログインする時に--local_infileが設定できないなら、設定ファイルに

[client]
loose-local-infile=1

と入れて設定すればいいんじゃねということでやってみました。
結論、ダメでした。

3)1行ずつループ処理で突っ込む

qiita.com
freeheroblog.com
なんか一番無難そうな方法。
csvから行を取り出してmap関数でそれぞれの変数に割り当てるのと、タプルで取り出してつっこむのとどちらがいいのかってところは悩むかもしれません。

4)あきらめてちまちま入れる

ファイル数が2〜3ぐらいなら正直こっちの方がいいかもしれない。
いっぱいコード書かなくてもいいし。

まとめ

とりあえず1行ずつループ処理でつっこむか、諦めてターミナルからちまちまインポートするのが良さげ?
なかなかめんどくさい事案だなぁと思いながら見ています。