Python3中SQLAlchemy如何正确执行带datetime条件的原生查询
问题原因
你之前的几种写法分别存在这些问题:
- 前两种字符串拼接SQL的写法,直接把datetime值插入语句后,生成的SQL里时间值没有被单引号包裹,数据库会把
2021-06-01 00:00:00识别成带减号的算术表达式,解析到空格后的时间分段就会抛出语法错误,和你看到的syntax error at or near "00"报错完全对应。 - 第三种参数化写法的错误点在于给SQL语句加了
f前缀,f-string会优先解析字符串内容,把你写的%s占位符当成普通字符处理,后续传入的参数无法和占位符匹配,自然执行失败。 - 额外逻辑问题:纯SELECT查询没有数据修改操作,不需要调用
session.commit(),多余的提交操作没有实际作用,还可能引发事务逻辑异常。
正确写法
修正原生SQL参数化写法
核心是去掉SQL字符串前的f前缀,不要手动拼接时间值,直接把解析好的datetime对象作为参数传给execute方法,psycopg2驱动会自动完成时间类型的适配,不需要手动加引号或者转格式:
from datetime import datetime def get_test(self, start_date, end_date): query = 'SELECT * from messages WHERE messages."timeStamp" > %s and messages."timeStamp" < %s;' start_dt = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S") end_dt = datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S") res = self.session.execute(query, (start_dt, end_dt)) return res.fetchall()
使用SQLAlchemy表达式API(推荐)
如果已经定义了messages表对应的模型类,用SQLAlchemy内置的查询接口可以避免手写SQL的引号、占位符错误,写法更简洁安全,也能天然规避SQL注入风险:
from datetime import datetime # 引入提前定义好的Messages表模型 # from models import Messages def get_test(self, start_date, end_date): start_dt = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S") end_dt = datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S") return self.session.query(Messages).filter( Messages.timeStamp > start_dt, Messages.timeStamp < end_dt ).all()
提示:绝对不要用f-string、字符串format的方式拼接带外部输入的SQL语句,会直接引发SQL注入风险,参数化查询是唯一安全的写法。
内容的提问来源于stack exchange,提问作者abdulaziz ibrahim
相关产品推荐
相关产品推荐

