web-dev-qa-db-ja.com

Python MySQL準備済みステートメントをサポートしていますか?

私は以前にPHPプロジェクトに取り組み、そこでは準備されたステートメントがSELECTクエリを20%高速にしました。

Pythonで動作するのだろうか?具体的にそれがそうであるかそうでないと言うものを見つけることができないようです。

47
rubayeet

直接答え、いいえ、そうではありません。

joshperry's answer は、代わりに何をするのかについての良い説明です。

同様の質問に対するユージンyの回答 から

MySQLdbを確認してください パッケージコメント

「パラメータ化」は、MySQLdbで文字列をエスケープし、MYSQL_STMT APIを使用する代わりに、文字列を盲目的にクエリに挿入することで行われます。その結果、ユニコード文字列は、データベースで受信される前に2つの中間表現(エンコードされた文字列、エスケープされたエンコードされた文字列)を通過する必要があります。

答えは「いいえ、ありません」です。

13
James McMahon

ほとんどの言語は、一般的なパラメーター化されたステートメントを実行する方法を提供します。Pythonも違いはありません。パラメーター化されたクエリを使用すると、ステートメントの準備をサポートするデータベースが自動的に実行されます。

pythonでは、パラメーター化されたクエリは次のようになります。

cursor.execute("SELECT FROM tablename WHERE fieldname = %s", [value])

パラメーター化の特定のスタイルは、ドライバーによって異なる場合があります。dbモジュールをインポートしてからprint yourmodule.paramstyle

PEP-249 から:

paramstyle

       String constant stating the type of parameter marker
       formatting expected by the interface. Possible values are
       [2]:

           'qmark'         Question mark style, 
                           e.g. '...WHERE name=?'
           'numeric'       Numeric, positional style, 
                           e.g. '...WHERE name=:1'
           'named'         Named style, 
                           e.g. '...WHERE name=:name'
           'format'        ANSI C printf format codes, 
                           e.g. '...WHERE name=%s'
           'pyformat'      Python extended format codes, 
                           e.g. '...WHERE name=%(name)s'
58
joshperry

MySQLdbパッケージ(mysqlと統合するための一種の事実上のパッケージ)のCursorオブジェクトのexecute()メソッドをざっと見てみると、(少なくともデフォルトでは)文字列の補間のみを行っているようです実際のパラメータ化されたクエリではなく、クォート:

if args is not None:
    query = query % db.literal(args)

これが文字列補間ではない場合、何ですか?

Executemanyの場合、実際にはループで実行するのではなく、挿入/置換を単一のステートメントとして実行しようとします。それはそれについてです、そこに魔法はないようです。少なくともデフォルトの動作ではありません。

編集:ああ、私はちょうどモジュロ演算子がオーバーライドされる可能性があることに気づきましたが、ソースを不正行為し、greppedしたように感じました。ただし、オーバーライドされたmodはどこにも見つかりませんでした。

10
shylent

これを理解しようとしている人のために、[〜#〜] yes [〜#〜]Python and MySQL。MySQL自体からMySQL Connector/Pythonを使用して、右カーソルをインスタンス化します。

https://dev.mysql.com/doc/connector-python/en/index.html

https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursorprepared.html

5
fromvega

Amitが推奨するSQLインターフェイスを使用すると、パフォーマンスのみを懸念する場合に機能します。ただし、ネイティブのPythonプリペアドステートメントのサポートがもたらす可能性があるSQLインジェクションに対する保護が失われます。Python 3には、PostgreSQLのプリペアドステートメントサポートを提供するモジュールがあります。MySQLの場合、「oursql」は真のプリペアドステートメントサポートを提供しているようです(他のモジュールのように偽造されていません)。

5
user304386

直接関係はありませんが、 この回答 SOの別の質問)には、「テンプレート化された」クエリの構文の詳細が含まれています。自動エスケープは、最も重要な機能...

パフォーマンスに関しては、カーソルオブジェクトのexecutemanyメソッドに注意してください。多数のクエリをまとめて一度にすべて実行し、doesによりパフォーマンスが向上します。

1
Michał Marczyk

解決策があります!

サーバー上のストアドプロシージャに入れて、Pythonからこのように呼び出すと、それらを使用できます...

cursor.callproc(Procedurename, args)

これは、mysqlとpythonのストアドプロシージャに関する素敵なチュートリアルです。

http://www.mysqltutorial.org/calling-mysql-stored-procedures-python/

0
whoopididoo