29

cursor.executeいくつかの理由で、2番目のパラメーターの内容に対してメソッドによって実行される暗黙的な引用を待つのではなく、文字列値の明示的な引用(構築された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_FUNCTIONPython DB API仕様で期待されるこのような低レベルですか( PEP 249ドキュメントでそのような機能を見つけることができませんでした)。そうでない場合は、おそらくPsycopg2がそのような機能を提供しますか?そうでない場合、おそらくDjangoはそのような機能を提供しますか?私はそのような関数を自分で書きたくないのですが...

4

10 に答える 10

33

わかりましたので、興味があったので、psycopg2 のソースを調べてみました。私はサンプルフォルダより先に進む必要はなかったことがわかりました:)

はい、これはpsycopg2固有です。基本的に、文字列を引用したいだけなら、次のようにします:

from psycopg2.extensions import adapt

print adapt("Hello World'; DROP DATABASE World;")

しかし、おそらくやりたいことは、独自のアダプターを作成して登録することです。

psycopg2 のサンプル フォルダーには、ファイル'myfirstrecipe.py'があり、特定の型を特別な方法でキャストして引用する方法の例があります。

やりたいことのオブジェクトがある場合は、「IPsycopgSQLQuote」プロトコルに準拠するアダプターを作成するだけです (myfirstrecipe.py-example の pydocs を参照してください...実際には、その名前を見つけることができる唯一の参照です。 ) オブジェクトを引用し、次のように登録します。

from psycopg2.extensions import register_adapter

register_adapter(mytype, myadapter)

また、他の例も興味深いものです。特に。「dialtone.py」「simple.py」

于 2008-11-23T11:47:54.167 に答える
17

mogrify関数を探していると思います。

例:

>>> cur.mogrify("INSERT INTO test (num, data) VALUES (%s, %s)", (42, 'bar'))
"INSERT INTO test (num, data) VALUES (42, E'bar')"
于 2014-07-05T20:46:46.157 に答える
2

独自の引用を避けるようにしてください。人々が指摘したように、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 つのリストとして扱うことができます。

于 2008-11-22T00:01:40.737 に答える
1

これはデータベースに依存します(iirc、mysqlは\エスケープ文字として許可しますが、oracleのようなものは引用符が2倍になることを期待しています: 'my '' quoted string')。

私が間違っている場合は誰かが私を訂正してくれますが、二重引用符の方法は標準的な方法です。

他の db 抽象化ライブラリ (sqlalchemy、cx_Oracle、sqlite など) が何を行っているかを調べる価値があるかもしれません。

値をバインドするのではなく、値をインライン化したいのはなぜですか?

于 2008-11-21T20:25:48.990 に答える
0

私はあなたがこれを正しい方法で行うためにあなたの回避の背後にある十分な理由を与えていないと思います。設計どおりにAPiを使用してください。次の人がコードを読みにくくし、壊れやすくするために、それほど努力しないでください。

于 2008-11-23T15:17:20.810 に答える
0

これはDB依存になります。たとえば、MySQLdb の場合、connectionクラスには、literalMySQL に渡すための正しいエスケープ表現に値を変換するメソッドがあります (これがcursor.execute使用されます)。

Postgres にも似たようなものがあると思いますが、DB API 2.0 仕様の一部として値をエスケープする機能はないと思います。

于 2008-11-21T20:07:31.693 に答える
0

psycopg 拡張ドキュメントによると、コード スニペットは次のようになります。

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()

于 2012-12-12T21:09:27.313 に答える
-1

djangoを使用する場合は、現在構成されているDBMSに自動的に適合されるクォート機能を使用することをお勧めします。

from django.db import backend
my_quoted_variable = backend.DatabaseOperations().quote_name(myvar)
于 2008-11-23T14:39:48.220 に答える
-2
import re

def db_quote(s):
  return "\"" + re.escape(s) + "\""

少なくとも MySQL で機能する単純な引用の仕事を行うことができます。本当に必要なのは、cursor.execute() のように機能する cursor.format() 関数ですが、実行する代わりに結果のクエリを返す点が異なります。クエリをまだ実行したくない場合があります。たとえば、最初にログに記録したり、実行する前にデバッグ用に出力したりしたい場合があります。

于 2013-02-07T23:32:41.990 に答える