9

記録のために、私はPythonとSQLliteを使用しています。必要なSQLを生成する関数がありますが、正しくないようです。

def daily(self, host=None, day=None):
    sql = "SELECT * FROM daily WHERE 1"
    if host:
        sql += " AND host = '%s'" % (host,)
    if day:
        sql += " AND day = '%s'" % (day,)
    return sql

後で複数の列と条件を追加する必要があります。

より良いアイデアはありますか?

編集: 正しく見えないのは、文字列から動的にSQLを構築しているということです。これは一般的に最善のアプローチではありません。SQLインジェクションのアタッチメントは、文字列を適切にエスケープする必要があります。一部の値がNoneであり、WHERE句の条件である必要がないため、プレースホルダーを使用できません。

4

2 に答える 2

15

文字列の書式設定を使用して値を含めることは本当に望ましくありません。SQL パラメータを介してデータベース API に任せます。

パラメータを使用すると、次のことができます。

  • データベースにステートメントを準備し、パフォーマンスを向上させるためにクエリ プランを再利用する機会を与えます。
  • 値を適切にエスケープするという頭痛の種から解放されます (SQL エスケープの許可や SQL インジェクション攻撃の回避を含む)。

SQLLiteは名前付き SQL パラメーターをサポートしているため、ステートメントとパラメーター付きの辞書の両方を返します。

def daily(self, host=None, day=None):
    sql = "SELECT * FROM daily"
    where = []
    params = {}
    if host is not None:
        where.append("host = :host")
        params['host'] = host
    if day is not None:
        where.append("day = :day")
        params['day'] = day
    if where:
        sql = '{} WHERE {}'.format(sql, ' AND '.join(where))
    return sql, params

次に、両方をに渡しcursor.execute()ます:

cursor.execute(*daily(host, day))

SQL の生成は急速に複雑になります。代わりに、 SQLAlchemy コアを参照して生成を行うことをお勧めします。

あなたの例では、次を生成できます。

from sqlalchemy import Table, Column, Integer, String, Date, MetaData

metadata = MetaData()
daily = Table('daily', metadata, 
    Column('id', Integer, primary_key=True),
    Column('host', String),
    Column('day', Date),
)
from sqlalchemy.sql import select

def daily(self, host=None, day=None):
    query = select([daily])
    if host is not None:
        query = query.where(daily.c.host == host)
    if day is not None:
        query = query.where(daily.c.day == day)
    return query

オブジェクトには、query追加のフィルターを適用したり、並べ替えたり、グループ化したり、他のクエリのサブセレクトとして使用したり、結合したり、最終的に送信して実行したりすることができます。その時点で、SQLAlchemy はこれを、接続している特定のデータベースに適合する SQL に変換します。

于 2013-03-19T10:04:21.910 に答える
3

完全を期すためだけに。pypika ライブラリは非常に便利であることがわかりました (ライブラリが許可されている場合):

https://pypika.readthedocs.io/en/latest/index.html

次のようなSQLクエリを作成できます。

from pypika import Query

q = Query._from('daily').select('*')
if host:
     q = q.where('host' == host)
if day:
     q = q.where('day' == day)
sql = str(q)
于 2019-12-06T09:13:42.193 に答える