読者です 読者をやめる 読者になる 読者になる

sqlite3でのエスケープ処理

データベースとしてsqlite3を使用していて,すごく今さらながら最近知ったことがあったのでメモ.

エスケープ処理

pythonで文字列を扱うときに,例えば\(バックスラッシュ)を

print '\'

なんてすると怒られるのは,pythonにおいて \ がエスケープに用いられているから.
何かしら特別な役割を持つ記号をそのまま文字として使いたい時に \ を使用します.
つまり,

print '\\'

とすれば \ をprintすることが出来ます.
特に正規表現を用いる際にエスケープを行うことが多いはず.
文字列中の \ を見つけたいならパターンとして

pattern = '\\\\'
regex = re.compile(pattern)

としなければならない.
ちなみに

pattern = r'\\'

というように文字列の前に r を付けることで文字列中の \ を特別扱いしない,
raw string 記法というものになります.

sqlite3でのエスケープ

データベースに問い合わせる時に叩くsql文において

sql = 'select word from wordlist where word = "%s"' % term
con = sqlite3.connect('database.db')
con.execute(sql).fetchone()

なんてすると term の中に変なもの入れられたりして予想外な動作をしかねない.
そこで,

sql = 'select word from wordlist where word = ?'
con = sqlite3.connect('database.db')
term = unicode(term.decode('utf-8'))
con.execute(sql, (term, )).fetchone()

とすると ? の位置にtermをエスケープ処理を行っていれてくれるので,
予想外な動作はしないはず.
文字列の文字コードunicode型にしないとうまくいかないようです.
また,4行目のように(term, )としないとうまくいかないようです.
なんでですかね.
2つ以上sqlに埋め込みたい場合は,

sql = 'select word from wordlist where word = ? and rowid = ?'
con = sqlite3.connect('database.db')
term = unicode(term.decode('utf-8'))
number = 100
con.execute(sql, (term, number)).fetchone()

ってやると出来てしまいます.
この場合は(term, number, )とはしなくてもエラー出ないですね.
よくわかんない☆(ゝω・)vキャピ

例のsql文もうちょいましなの無かったんですかね...w