いくつかの理由で、2番目のパラメーターの内容に対してcursor.execute
メソッドによって実行される暗黙的な引用を待つのではなく、文字列値の明示的な引用(構築されたSQLクエリの一部になる)を実行したいと思います。
「暗黙の引用」とは、次のことを意味します。
value = "Unsafe string"
query = "SELECT * FROM some_table WHERE some_char_field = %s;"
cursor.execute( query, (value,) ) # value will be correctly quoted
私はそのようなものを好むでしょう:
value = "Unsafe string"
query = "SELECT * FROM some_table WHERE some_char_field = %s;" % \
READY_TO_USE_QUOTING_FUNCTION(value)
cursor.execute( query ) # value will be correctly quoted, too
そのような低レベルのREADY_TO_USE_QUOTING_FUNCTION
はPython DB API仕様で期待されています( PEP 249 ドキュメントでそのような機能を見つけることができませんでした)。そうでない場合は、おそらくPsycopg2そのような関数を提供しますか?そうでない場合は、おそらくDjangoはそのような関数を提供しますか?私はそのような関数を自分で作成したくないです...
さて、私は興味があったので、psycopg2のソースを調べました。実例フォルダより先に進む必要はなかったことがわかりました:)
はい、これはpsycopg2固有です。基本的に、文字列を引用したいだけの場合は、次のようにします。
from psycopg2.extensions import adapt
print adapt("Hello World'; DROP DATABASE World;")
しかし、おそらくやりたいことは、独自のアダプターを作成して登録することです。
Psycopg2のexamplesフォルダーには、ファイル 'myfirstrecipe.py' があります。特定のタイプを特別な方法でキャストおよび引用する方法の例があります。
やりたいことのオブジェクトがある場合は、「IPsycopgSQLQuote」プロトコルに準拠するアダプターを作成するだけです(myfirstrecipe.py-exampleについてはpydocsを参照してください...実際、その名前を見つけることができるのはそれだけです。 )オブジェクトを引用し、次のように登録します。
from psycopg2.extensions import register_adapter
register_adapter(mytype, myadapter)
また、他の例も興味深いものです。特に 'dialtone.py' および 'simple.py' 。
mogrify 関数を探していると思います。
例:
>>> cur.mogrify("INSERT INTO test (num, data) VALUES (%s, %s)", (42, 'bar'))
"INSERT INTO test (num, data) VALUES (42, E'bar')"
あなたはあなた自身の引用をすることを避けるように努めるべきです。人々が指摘しているように、それはDB固有であるだけでなく、引用の欠陥がSQLインジェクションのバグの原因です。
クエリと値を別々に渡したくない場合は、パラメータのリストを渡します。
def make_my_query():
# ...
return sql, (value1, value2)
def do_it():
query = make_my_query()
cursor.execute(*query)
(おそらくcursor.executeの構文が間違っています)ここでのポイントは、cursor.executeが多数の引数を取るからといって、それらすべてを個別に処理する必要があるという意味ではないということです。それらを1つのリストとして扱うことができます。
私はあなたがこれを正しい方法で行うためにあなたの回避の背後にある十分な理由を与えているとは思わない。設計どおりにAPiを使用してください。次の人がコードを読みにくくし、壊れやすくするために、それほど努力しないでください。
PyPika SQLステートメントを作成するための別の適切なオプション。使用例(プロジェクトのホームページの例に基づく):
>>> from pypika import Order, Query
>>> Query.from_('customers').select('id', 'fname', 'lname', 'phone').orderby('id', order=Order.desc)
SELECT "id","fname","lname","phone" FROM "customers" ORDER BY "id" DESC
これはデータベースに依存します(iirc、mysqlはエスケープ文字として\
を許可しますが、Oracleのようなものは引用符が2倍になることを期待します:'my '' quoted string'
)。
私が間違っていれば誰かが私を訂正しますが、二重引用法が標準的な方法です。
他のdb抽象化ライブラリ(sqlalchemy、cx_Oracle、sqliteなど)が何をするかを調べる価値があるかもしれません。
私は尋ねなければなりません-なぜあなたはそれらをバインドする代わりに値をインライン化したいのですか?
psycopg extension docs によると、コードスニペットは次のようになります。
_from psycopg2.extensions import adapt
value = "Unsafe string"
query = "SELECT * FROM some_table WHERE some_char_field = %s;" % \
adapt(value).getquoted()
cursor.execute( query ) # value will be correctly quoted, too
_
getquoted
関数は、引用符で囲まれたエスケープされた文字列としてvalue
を返すため、"SELECT * FROM some_table WHERE some_char_field = " + adapt(value).getquoted()
に移動することもできます。
これはDBに依存します。たとえば、MySQLdbの場合、connection
クラスにはliteral
メソッドがあり、MySQLに渡すために値を正しいエスケープ表現に変換します(これがcursor.execute
使用)。
Postgresにも似たようなものがあると思いますが、DB API2.0仕様の一部として値をエスケープする機能はないと思います。