Python 动态SQL WHERE子句生成
作为记录,我使用Python和SQLlite。我有一个可以生成所需SQL的工作函数,但它似乎不正确Python 动态SQL WHERE子句生成,python,sql,sqlite,language-agnostic,sql-injection,Python,Sql,Sqlite,Language Agnostic,Sql Injection,作为记录,我使用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
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注入attacs,需要正确转义字符串。我无法使用占位符,因为某些值为无,不需要处于WHERE子句条件下。您确实不想使用字符串格式来包含值。通过SQL参数将其留给数据库API
使用参数可以:
- 让数据库有机会准备语句并重用查询计划以获得更好的性能
- 省去了正确转义值的麻烦(包括避免允许SQL转义和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
然后将两者都传递给游标。执行():
SQL生成很快就会变得复杂,您可能需要查看以执行生成
例如,您可以生成:
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
查询
对象可以对其应用附加过滤器,对其进行排序、分组、用作其他查询的子选择、连接并最终发送以执行,此时SQLAlchemy会将其转换为适合您所连接的特定数据库的SQL。只是为了完整性。我发现pypika库非常方便(如果允许库的话):
它允许像这样构造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)
感谢SQLAlchemy链接。但这超出了范围。仅限标准/内置模块。@Ayman:那么至少要使用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)