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

  • 0
    Like
  • 0
    Comment

    今回のお題

    一部通知用のデータをとりあえず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()