Python プログラムからの MySQL 操作 で Insertが反映されない!!
後学のために記しておきます。
はい、私はにわかPython使いです。他の言語も扱うのでPython命でもありません。
今回丸々2日間ハマってしまいました。
MySQLでなぜか Insert だけ反映されない!!
こういうプログラムでした。
CSVファイルを読み込んでMySQLのデータベースのテーブルに格納します。
難しいことはありません。
MySQLのライブラリは python-MySQL 。
プログラム冒頭で元となるテンプレートテーブルをコピーしてテーブルを作成します。
import MySQLdb
conn = MySQLdb.connect(host="extdbsrv", db="test", user="user", passwd="xxx", charset="utf8")
cursor = conn.cursor()
sql = "CREATE TABLE test like table_template"
cursor.execute(sql)
テンプレートテーブルはphpMyAdminで作成します。
プログラムで生成しないのは、コメント付のテーブルを作成するのにphpMyAdminが便利だからです。
プログラムを実行します。正常にテーブルがコピーされます。
もちろんこの後にもプログラムが続きます。
CSVファイルをオープンして1行ずつ読み込み、テーブルにInsertしていきます。
カラムが50個もあり、SQLで書き込む処理が大変です。
#なぜかデータベースにデータの書き込みがされない!!
プログラムエラーは出なくなりましたが、なぜかデータベースに反映されず書き込まれません。
もちろんSQLエラー(MySQLが吐くエラー)も出てないようです。
先にテーブルコピーはできているので、DBに接続できてますし、書き込み権限はあるはずです。
sql = "INSERT INTO hwdata01 ( id , prefectural_id ) values (NULL,1)"
cursor.execute(sql)
プライマリーキーだけinsertするプログラムにしましたが、レコードは追加されず。。。
#トラブルシューティング
プログラムを眺めていてもどうにも原因がわかりませんが、あわてずトラブルシューティングです。
- ローカル(Windows)環境で作成していましたが、Linuxサーバー上でも同じPythonプログラムを実行 => ダメ
- DB接続アカウントに全権限を与えた => ダメ
- 接続書き込み先のサーバーを変えてみてテスト => ダメ
- CSV読み込みはやめて仮データをInsertするだけのプログラムに変更 => ダメ
- phpMyAdminから同じSQL文を実行 => 書き込みされる
- MySQLのCLIクライアントから同じSQL文を実行 => 書き込みされる
結局はPythonからの書き込みだけInsertが反映されません。
#不思議な現象! autoincrement はカウントされている
CLIクライアント(MySQLコマンドライン)からinsertやselectをしていて気づきましたが、autoincrement(自動連番)は機能しているようです。
pythonプログラムでinsertすると、レコードは挿入されませんが、ちゃんとidが1増えているのです。
phpMyAdminの画面ですが、id が飛び飛びになっています。
このidが書き込みされているのは、CLIクライアントから操作した場合です。
ますますわからなくなりました。
#そうかコミットされてないんじゃないか
色々検索をしている途中に、コミットされてないんじゃないかという疑念がわきました。
Python以外は気にしなくていいんですが(良くないですが)、他の言語は自動的にファイルクローズやDBコミットを自動的にやってくれていることが多いので、極端に気にしなくてもだいたい何とかなります。
気にしなかったわけではないのですが、ファイルのオープンも復数していたので目に付きませんでした。
commit/close 文をプログラムの最後に付け加えます。
cursor.close
conn.commit
conn.close
これで何とかと願いながら実行しますが、特に挙動は変わらず。。。
#もしやと思い
ここまで2日間費やし、記載していないことでもできることは色々やりました。
もしやと思い、命令文の後ろに括弧(カッコ)を付け加えます。
cursor.close()
conn.commit()
conn.close()
結果は・・・思ったようにInsertされました。
何だったんでしょうか。カッコをつけるつけないはあまり気にしませんでした。
というより、つけなければエラーか警告を吐いてくれればいいのに。
Python使いの方々は with 文を使って自動的にコミットさせろとか言うんでしょうけど。