文字列の書式設定を使用して値を含めることは本当に望ましくありません。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 に変換します。