Python
MySQL
python2.7

Python2.7でPyMySQLを使用してSQLを実行する

More than 1 year has passed since last update.

今回のお題

一部通知用のデータをとりあえずMySQLに溜め込もうかなと思いますので、
MySQLにSELECTしてみて、結果を取れればと思います。

簡単なテーブルの作成

とりあえずブログを書く人を順番に指名してSlackに通知するが最終目標なので、
仮で下記のような構造のテーブルを作ります。
テーブル名:test

id name target_flag
1 Aさん 1
2 Bさん 1
3 Cさん 1
4 Dさん 0
5 Eさん 1

idはPK、nameは仮の名前、target_flagはこの処理の対象者か否かです(1が対象者)
こちらのテーブルにアクセスし、target_flag=1のデータだけ取得します。

PyMySQLでのアクセスを試してみる

Anaconda(python)からMySQLを使う

こちらを参考にさせていただきました。
書き方は違いますが、やってることが一緒ですね。

mysql.py
# -*- coding: utf-8 -*-
# # モジュール読み込み
import pymysql.cursors

def lambda_handler(event, context):
    # MySQLに接続する
    conn = pymysql.connect(host='ホスト',
                                user='ユーザ名',
                                password='パスワード',
                                db='DB名',
                                charset='utf8',
                                cursorclass=pymysql.cursors.DictCursor)
    # select
    # SQLを実行する
    cursor = conn.cursor()
    sql = "SELECT * FROM test WHERE target_flag = 1"
    cursor.execute(sql)

    # Select結果を取り出す
    rets = cursor.fetchall()
    for r in rets:
        print(r)

    # MySQLから切断する
    conn.close()

実行すると、下記の状態で出力されましたので無事に取れているかと思います。

{u'target_flag': 1, u'id': 1, u'name': u'A\u3055\u3093'}
{u'target_flag': 1, u'id': 2, u'name': u'B\u3055\u3093'}
{u'target_flag': 1, u'id': 3, u'name': u'C\u3055\u3093'}
{u'target_flag': 1, u'id': 5, u'name': u'E\u3055\u3093'}

ちなみに、cursorclass=pymysql.cursors.DictCursorを外すと、結果は下記になります。

{1, 1, u'A\u3055\u3093'}
{1, 2, u'B\u3055\u3093'}
{1, 3, u'C\u3055\u3093'}
{1, 5, u'E\u3055\u3093'}

アクセスの仕方が変わるので、、cursorclass=pymysql.cursors.DictCursorは付けたほうが良いと思います!

今回ハマったこと

上記のソースなんですが、1回目は正常に取れましたが、2度目からコンソールに何も出力されない事象が起きました。
そこで、改めてソースを見直して、これか?と思う箇所を直して見ました。

mysql.py
# -*- coding: utf-8 -*-
# # モジュール読み込み
import pymysql.cursors

def lambda_handler(event, context):
    # MySQLに接続する
    conn = pymysql.connect(host='ホスト',
                                user='ユーザ名',
                                password='パスワード',
                                db='DB名',
                                charset='utf8',
                                cursorclass=pymysql.cursors.DictCursor)
    # select
    # SQLを実行する
    cursor = conn.cursor()
    sql = "SELECT * FROM test WHERE target_flag = 1"
    cursor.execute(sql)

    # Select結果を取り出す
    rets = cursor.fetchall()
    for r in rets:
        print(r)
    # cursorを閉じる
    cursor.close()

    # MySQLから切断する
    conn.close()

そうです。CURSORのクローズをしていませんでした・・・今一ここでいうCURSORがどういったものか理解できてませんが、1回目の実行結果をfeatchallで全部取得→全て読み込み終える→closeしてないのでメモリ上残っている?→2回目以降も同じ箇所の読み取りなので、メモリ情報変わらず?
なんでしょうか・・・?ちょっとこの辺りが気になるので、落ち着いたら調べたり・色々試したりしたいですね。

INSERTやUPDATE、DELETEについて

これはまぁ、単純にSQL文を書いて実行し、最後にcommitするだけでした。

    cursor = conn.cursor()
    sql = "DELETE * FROM test WHERE target_flag = 0"
    cursor.execute(sql)
    conn.commit()