タイトルを逆にいうとPyMySQLのプレースホルダには qmark(?), numeric(:1), named(:name) は実装されてないようです。
※ この記事は、 version 1.0.2 の時点の PyMySQLについて書いています。将来的に他のプレースホルダーも実装されるかもしれません。
!pip freeze | grep PyMySQL
PyMySQL==1.0.2
pep249では、paramstyle として次の5つが定められています。
名前 | 説明 | 例 |
---|---|---|
qmark | Question mark style | WHERE name=? |
numeric | Numeric, positional style | WHERE name=:1 |
named | Named style | WHERE name=:name |
format | ANSI C printf format codes | WHERE name=%s |
pyformat | Python extended format codes | WHERE name=%(name)s |
PyMySQLはpep249に従って実装さているので、この5つが全部使えるのかなと思って試したら、そうなってないことに気づきました。
タイトルにも書きました通り、実装されているのは format と pyformat だけです。
とはいえ、実用的なことを考えると、各値に名前をつけないときは、format、名前をつけたいときはpyformatを使えばいいので、この二つで十分だと思います。
実際にやってみます。
テーブルは前の記事で作ったものをそのまま使います。
まずDBに接続します。接続情報は各自の環境の値をご利用ください。
import pymysql.cursors
con_args = {
"host": "{RDSのエンドポイント/同サーバーのDB場合はlocalhost}",
"user": "{ユーザー名}",
"password": "{パスワード}",
"database": "{DB名}",
"cursorclass": pymysql.cursors.DictCursor
}
connection = pymysql.connect(**con_args)
まず、 format スタイルから。サンプルコードなどで頻繁に見かけるのはこれです。
with connection.cursor() as cursor:
sql = "SELECT id, email, password FROM users WHERE email=%s"
cursor.execute(sql, ('webmaster@python.org',))
result = cursor.fetchone()
print(result)
# {'id': 1, 'email': 'webmaster@python.org', 'password': 'very-secret'}
続いて、 pyformat。 このサンプルコードではありがたみがないですが、多くのプレースホルダーを使うクエリでは可読性向上に期待できます。
with connection.cursor() as cursor:
sql = "SELECT id, email, password FROM users WHERE email=%(email)s"
cursor.execute(sql, {"email": "webmaster@python.org"})
result = cursor.fetchone()
print(result)
# {'id': 1, 'email': 'webmaster@python.org', 'password': 'very-secret'}
qmark だと cursor.execute でエラーになります。 (エラーになるので例外処理入れてます。)
with connection.cursor() as cursor:
sql = "SELECT id, email, password FROM users WHERE email=?"
try:
cursor.execute(sql, ('webmaster@python.org',))
result = cursor.fetchone()
print(result)
except Exception as e:
print(e)
# not all arguments converted during string formatting
numeric も同様。
with connection.cursor() as cursor:
sql = "SELECT id, email, password FROM users WHERE email=:1"
try:
cursor.execute(sql, ('webmaster@python.org',))
result = cursor.fetchone()
print(result)
except Exception as e:
print(e)
# not all arguments converted during string formatting
named もエラーになります。これだけエラー文が違います。
with connection.cursor() as cursor:
try:
sql = "SELECT id, email, password FROM users WHERE email=:email"
cursor.execute(sql, {"email": "webmaster@python.org"})
result = cursor.fetchone()
print(result)
except Exception as e:
print(e)
# (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':email' at line 1")