LoginSignup
9

More than 3 years have passed since last update.

posted at

pymysqlのプレースホルダは数値と文字列を区別する

結論

Pythonでmysqlを使っていたらプレースホルダで躓いたので調べました。
結果はタイトルの通り。

直感的に数値は%dを使用しましたが、全て%sで良く、数値はクォートされずに展開されていました。

経緯

こんなコードでインサートを実行したら

import pymysql as pm
import traceback

DATABASE = {
    'host': 'localhost',
    'db': 'test',
    'user': 'root',
    'password': 'test',
    'port': 3306,
    'cursorclass': pm.cursors.DictCursor
}

con = pm.connect(**DATABASE)
try:
    with con.cursor() as cur:
        sql = """
            insert into corporation (id, name)
            values (%d, %s)
            ;
        """
        cur.execute(sql, (1,'テスト会社'))
    con.commit()
except:
    traceback.print_exc()
    con.rollback()
finally:
    con.close()

「%dは数値入れろ、文字列じゃねーよカス(意訳)」と怒られたのでインターネットをグーグルしたら
issueに回答が書いてありました。
曰く、プレースホルダは%sで良く、数値か文字列か適切に展開してくれるとのこと。
TypeError: %i format: a number is required, not str #329

Traceback (most recent call last):
  File "<ipython-input-4-84616a96211d>", line 21, in <module>
    cur.execute(sql, (1,'テスト会社'))
  File "/home/sysman/.pyenv/versions/anaconda3-5.3.1/envs/script/lib/python3.7/site-packages/pymysql/cursors.py", line 168, in execute
    query = self.mogrify(query, args)
  File "/home/sysman/.pyenv/versions/anaconda3-5.3.1/envs/script/lib/python3.7/site-packages/pymysql/cursors.py", line 147, in mogrify
    query = query % self._escape_args(args, conn)
TypeError: %d format: a number is required, not str

クエリのエスケープ処理箇所

%dとしていたところを%sに変更してデバッガで確認したら以下のように数値は数値として展開されていて、すごいなと思いました。(小学生並)

cursors.py
展開後のクエリ

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
9