リストの要素分のプレースホルダを用意し、安全に値を渡します。
python
1stmt_formats = ','.join(['%s'] * len(names))
2db.execute("SELECT name, age, sex FROM info IN (%s)" % stmt_formats, tuple(names))
段階を追って説明すると下記のようになります。
①
stmt_formats = ','.join(['%s'] * len(names))
これによって、names の要素の数だけ プレースホルダ「%s」がカンマで区切られた文字列が作成されます。
②
"SELECT name, age, sex FROM info IN (%s)" % stmt_formats
この部分で、IN の右にある %s が、さきほど作成した stmt_formats (「%s,%s」)に置換されます。
・作成されるSQL文
"SELECT name, age, sex FROM info IN (%s,%s)"
③
python
1db.execute("SELECT name, age, sex FROM info IN (%s)" % stmt_formats, tuple(names))
execute 関数の第2引数に、タブルを指定することで、プレースホルダに内容が渡されます。
SQL文は、 "SELECT name, age, sex FROM info IN (%s,%s)"
tuple(names) ===> ("太郎", "史郎")
なので、1番目の %s に「太郎」2番目の %s に「史郎」が渡されます。
仮に太郎、史郎がSQLインジェクションの意図を持つ文字列であったとしても、エスケープされるため安全です。
※ f ストリングによって SQL を直接組み立てる方法は、SQL インジェクションを起こす危険があるため、以下のような場合を除き、安易に使用すべきではありません。
<f ストリング等での組み立てでもよい場合>
- 渡す変数が(安全な値の)固定値である。
- 固定値でない場合は、渡す変数が、別の処理であらかじめエスケープされている。
(質問からは、固定値かどうか、エスケープしているかどうかが確定的には不明だったため)