web-dev-qa-db-ja.com

Python、SQLAlchemyはconnection.executeでパラメーターを渡します

SQLAlchemy connection.execute(sql)を使用して、選択結果をマップの配列に変換しています。次のコードを持っている

_
def __sql_to_data(sql):
    result = []
    connection = engine.connect()
    try:
        rows = connection.execute(sql)
        for row in rows:
            result_row = {}
            for col in row.keys():
                result_row[str(col)] = str(row[col])
            result.append(result_row)
    finally:
        connection.close()
    return result
_

そして、例えば.

__sql_to_data(sql_get_scan_candidate)
return __sql_to_data(sql_get_profile.format(user_id))

質問手順を変更して、次のようなことを可能にする方法

return __sql_to_data(sql_get_profile,user_id)
22
Denis

チュートリアル は、このための非常に良い例を示しています:

_>>> from sqlalchemy.sql import text
>>> s = text(
...     "SELECT users.fullname || ', ' || addresses.email_address AS title "
...         "FROM users, addresses "
...         "WHERE users.id = addresses.user_id "
...         "AND users.name BETWEEN :x AND :y "
...         "AND (addresses.email_address LIKE :e1 "
...             "OR addresses.email_address LIKE :e2)")
SQL>>> conn.execute(s, x='m', y='z', e1='%@aol.com', e2='%@msn.com').fetchall() 
[(u'Wendy Williams, [email protected]',)]
_

最初に、SQL文字列を取得し、それを sqalchemy.sql.text() に渡します。これは必須ではありませんが、おそらく良い考えです...

Text()がプレーン文字列に対して提供する利点は、バインドパラメータ、ステートメントごとの実行オプション、およびバインドパラメータと結果列の型指定動作に対するバックエンド中立的なサポートです。文字通り指定されます。

text()を使用しなかった場合でも、sql.format(...)を使用しないでください。これにより、 SQLインジェクション 攻撃のリスクが高まります。

次に、キーワードパラメータを使用して、既に使用している execute() 関数の実際の引数を指定できます。

さて、あなたの例には、実行機能をラップする関数があります。したがって、これを複数のクエリに使用する場合は、パラメーターが引数を受け取ることができるようにする必要があります。これは辞書として非常に簡単にできます:

_def _sql_to_data(sql, values):
    ...
    conn.execute(sql, values)
_

valuesは辞書になります。このように関数を使用できます...

_sql = 'SELECT ...'
data = { 'user_id' : 3 }
results = _sql_to_data(sql, data)
_

パラメータとしてキーワードを使用することは、execute()関数の引数を指定する1つの方法にすぎません。いくつかの異なる方法で、その関数の ドキュメント を読むことができます。

49
Mark Hildreth