うさぎ好きエンジニアの備忘録

うさぎたちに日々癒されているエンジニアが業務で直面したもの & 個人的な学習メモを残していきます。

Python3 + mysql-connector-pythonでMySQLを触る

PythonからMySQLをいじる必要があったので、その際の備忘録。

今回の実行環境

必要なパッケージのインストール

$ pip install mysql-connector-python

使い方

データベースに接続する(コネクションの作成)

こんな感じ。

import mysql.connector as mysqldb

conn = mysqldb.connect(
  host = host,
  port = port,
  user = user,
  password = password,
  database = database
  )

conn.ping(reconnect=True)

conn.ping(reconnect=True)で接続が切れた時に再接続を行ってくれるように設定。ちなみに正常に接続できているかは以下のようにすることで確認可能。

print(conn.is_connected())

基本的なSQLの実行方法

DELETE / UPDATE / INSERT / SELECTなど、何かしらのSQLを実行したい場合、cur = conn.cursor()のようにカーソルを作成してから、cur.execute(..)を使えば良い。

cur = conn.cursor()

cur.execute("CREATE TABLE sample_table;")
cur.execute("INSERT INTO sample_table VALUES (1, 'hoge', 'fuga')")
cur.execute("SELECT * FROM sample_table;")

INSERT

INSERTしたい場合、前述したようにcur.execute(..)でINSERT文を記述すれば良い。また、cur.executemany(..)を使うことで複数のレコードを一度に挿入することが可能。

cur = conn.cursor()

# データを1つだけ挿入
cur.execute("INSERT INTO sample_table VALUES (1, 'hoge', 'fuga')")


# 複数のデータを一気に挿入
records = [
  (1, 'hoge', 'fuga'),
  (2, 'hoge', 'fuga'),
  (3, 'hoge', 'fuga'),
  (4, 'hoge', 'fuga')
  ]
cur.executemany("INSERT INTO sample_table VALUES (%s, %s, %s)", records)

conn.commit()

conn.commit()しないと操作が反映されないので必ず実行すること。

SELECT

SELECT文で取得した結果は、fetchall()fetchone()を使ってアクセスする。

以下は取得した結果全件にアクセスする場合。

cur.execute("SELECT * FROM sample_table;")
rows = cur.fetchall()

for row in rows:
  print(rows)

1件だけ取得したい場合はfetchone()を使う。

cur.execute("SELECT * FROM sample_table;")
print(cur.fetchone())

また取得する件数を制限したい場合はfetchmany(size=..)を使う。

cur.execute("SELECT * FROM sample_table;")
print(cur.fetchmany(size=10))

コネクションのクローズ

DBでの作業が終わったら以下のようにコネクションをクローズする。

cur.close()
conn.close()

mysql.connector.errors.InternalError: Unread result found

fetchone()したら以下のようなエラーが出た。

mysql.connector.errors.InternalError: Unread result found

どうやらカーソルがバッファされていない場合、lazilyな挙動をするらしい。fetchone()などはクエリの実行結果から1件のみフェッチする (fetcymany()だと複数件フェッチする)といった動作をするが、バッファしていないと、「今所得した実行結果以降のデータがまだ揃っていないよ!」という感じで怒る模様。

以下のようにbuffered=Trueを設定してあげることで、裏でコネクタが全ての行をフェッチしてくれるのでエラーが出なくなる。

conn.cursor(buffered=True)