在Python的SQL函数中传入非日期时间类型参数的问题
问题分析与解决方案
核心问题
你的query2存在两个关键问题导致无法返回结果:
- 未使用f-string语法,
{camp1}这类变量不会被实际参数值替换,SQL语句里仍是原样的{camp1},数据库无法匹配到数据 - SQL中字符串类型的值必须用单引号包裹,即便变量被替换,没有单引号的话,
Camp_2022_04会被数据库解析为标识符(比如列名),而非字符串值
修复后的基础写法
先解决语法问题,将query2改为f-string,并给字符串参数加上单引号:
def Camp_eval(start_date,end_1M,camp1,camp2,camp3): query1 = f"""SELECT CONTACT_NUMBER, OUTCOME_DATE FROM DATABASE1 where OUTCOME_DATE >= (to_date('{start_date}', 'dd/mm/yyyy')) and OUTCOME_DATE < (to_date('{end_1M}', 'dd/mm/yyyy'))""" # 修复后的query2:启用f-string,为字符串参数添加单引号 query2 = f"""SELECT CONTACT_NUMBER FROM DATABASE2 WHERE (CAMP_NAME = '{camp1}' or CAMP_NAME = '{camp2}' or CAMP_NAME = '{camp3}')""" Camp_eval('01/04/2022','01/05/2022','Camp_2022_04','Camp_2022_05','Camp_2022_06')
生产环境推荐:参数化查询
直接用f-string拼接SQL存在SQL注入风险,推荐使用数据库驱动的参数化查询功能(不同数据库驱动语法略有差异,以下以Oracle为例):
import cx_Oracle def Camp_eval(start_date,end_1M,camp1,camp2,camp3): # 建立数据库连接(实际使用时需做好连接管理) conn = cx_Oracle.connect("user/password@host:port/service") cursor = conn.cursor() # 参数化日期查询:避免字符串拼接,驱动自动处理格式 query1 = """SELECT CONTACT_NUMBER, OUTCOME_DATE FROM DATABASE1 where OUTCOME_DATE >= to_date(:start_date, 'dd/mm/yyyy') and OUTCOME_DATE < to_date(:end_1M, 'dd/mm/yyyy')""" cursor.execute(query1, start_date=start_date, end_1M=end_1M) result1 = cursor.fetchall() # 参数化字符串查询:用IN语句简化逻辑,驱动自动处理引号 query2 = """SELECT CONTACT_NUMBER FROM DATABASE2 WHERE CAMP_NAME IN (:camp1, :camp2, :camp3)""" cursor.execute(query2, camp1=camp1, camp2=camp2, camp3=camp3) result2 = cursor.fetchall() cursor.close() conn.close() return result1, result2 Camp_eval('01/04/2022','01/05/2022','Camp_2022_04','Camp_2022_05','Camp_2022_06')
参数化查询会自动处理字符串的引号包裹,同时彻底规避SQL注入风险,是生产环境的标准写法。
内容的提问来源于stack exchange,提问作者MOA
相关产品推荐
相关产品推荐

