Python调用Oracle SQL用to_date按年月筛选时间戳报ORA-00932排查
错误原因
一共3个核心问题:
- 比较值类型错误:等号右侧写的
2019-05没有加引号,Oracle会把它识别为算术表达式(2019减5,计算结果是数值2014),而左侧to_date()返回的是DATE类型,类型不匹配直接触发ORA-00932报错。 - 函数用法错误:
to_date()的作用是把字符串按指定格式转成日期类型,而INSERT_DATE本身已经是时间戳/日期类型,直接传入to_date()会触发Oracle隐式类型转换,不仅逻辑不可控,还容易出现格式不匹配的隐性错误。 - 匹配逻辑错误:就算给右侧值加了引号,
to_date('2019-05','YYYY-MM')生成的是2019年5月1日0点的日期值,直接和带日、时分秒的原日期值做相等判断,只能匹配5月1日0点的记录,筛不出整个5月的数据。
另外原SQL里'KNEU/TEREX'and之间缺少空格,属于书写不规范问题,部分场景下可能触发解析错误。
修正方法
优先推荐性能更好的范围查询写法,该写法可以命中INSERT_DATE字段上的索引,大表查询效率更高:
sql3 = """ select * from location where domain_name = 'KNEU/TEREX' and INSERT_DATE >= to_date('2019-05-01', 'YYYY-MM-DD') and INSERT_DATE < to_date('2019-06-01', 'YYYY-MM-DD') """ dfotm4 = pd.read_sql_query(sql3, connection3)
逻辑说明:筛选时间大于等于5月1日0点、小于6月1日0点的所有记录,刚好覆盖2019年5月全量时间点,和期望输出完全匹配。
如果表数据量小,不在意索引性能,也可以用格式化字符串匹配的写法,逻辑更直观:
sql3 = """ select * from location where domain_name = 'KNEU/TEREX' and to_char(INSERT_DATE, 'YYYY-MM') = '2019-05' """ dfotm4 = pd.read_sql_query(sql3, connection3)
逻辑说明:用to_char()把日期类型的INSERT_DATE转成YYYY-MM格式的字符串,再和字符串'2019-05'做相等判断,也能正确筛出5月所有数据。
内容的提问来源于stack exchange,提问作者aeapen
相关产品推荐
相关产品推荐

