You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决Tkinter日历get_date()日期与Oracle datetime字段匹配查询的报错问题

解决Tkinter日历get_date()日期与Oracle datetime字段匹配查询的报错问题

嘿,我看你被Tkinter日历日期和Oracle datetime字段的查询报错给难住了,咱们一步步把这个问题解决掉!

先说说你当前代码里的几个核心问题:

  1. 直接拼接字符串到SQL的坑:你把转换后的日期字符串直接拼进SQL语句,不仅容易因为Oracle的会话日期格式设置不同触发ORA-01861格式不匹配错误,还存在严重的SQL注入风险,这在生产环境里绝对是要避免的。
  2. 日期转换的冗余操作:你把日历获取的日期转成带时分秒的字符串,但其实完全没必要手动做这个转换,Python的日期对象可以直接通过参数绑定传给Oracle驱动,驱动会自动处理格式匹配。
  3. 之前的TypeError根源:最开始你直接用get_date()返回的Timestamp或datetime.date对象拼接字符串,Python自然会报错“不能把字符串和日期对象拼接”,后来你转成了字符串,但还是没解决根本的格式和安全问题。

下面给你两种解决方式,优先推荐第一种:

方式一:用参数绑定直接传Python日期对象(最推荐)

这种方式彻底规避格式问题和SQL注入,代码也更简洁:

from datetime import datetime

# 获取日历的日期,假设get_date()返回的是datetime.date对象
Fecha = self.cal1.get_date()
# 把date对象转成datetime对象(时分秒设为0,匹配Oracle的datetime字段)
fecha_dt = datetime.combine(Fecha, datetime.min.time())

# 写SQL的时候用占位符(Oracle用:1这种位置占位符,或者命名占位符都可以)
sql = """
SELECT t3.DESCRIPTION as ASSET_DESCRIPTION 
FROM maximo.BTV_workorder T1 
INNER JOIN maximo.BTV_PM t2 ON t2.Assetnum=T1.Assetnum 
LEFT JOIN maximo.BTV_ASSET t3 ON T1.ASSETNUM=t3.ASSETNUM  
WHERE T1.istask='1' 
  AND T1.SITEID='ALBAL' 
  AND T1.STATUS='COMP' 
  AND t2.STATUS='ACTIVE' 
  AND t1.STATUSDATE = :target_date
"""

# 执行SQL时传入参数,驱动会自动处理日期格式转换
cursor.execute(sql, [fecha_dt])
# 或者用命名参数更清晰:cursor.execute(sql, target_date=fecha_dt)

为什么推荐这个方法?

  • Oracle驱动会自动把Python的datetime对象转换成Oracle能识别的datetime格式,完全不会出现ORA-01861错误。
  • 彻底避免SQL注入,这是生产环境代码的基本要求。
  • 不用手动处理字符串拼接,自然不会再出现TypeError。

方式二:用TO_DATE函数指定格式(不推荐,仅作参考)

如果你一定要用字符串转换的方式,那必须用Oracle的TO_DATE函数明确指定日期格式,同时依然用参数绑定(别再直接拼接了!):

Fecha = self.cal1.get_date()
# 转成带时分秒的字符串
fecha_str = Fecha.strftime("%Y-%m-%d %H:%M:%S")

# 用TO_DATE把字符串转成Oracle日期,同时用占位符传参
sql = """
SELECT t3.DESCRIPTION as ASSET_DESCRIPTION 
FROM maximo.BTV_workorder T1 
INNER JOIN maximo.BTV_PM t2 ON t2.Assetnum=T1.Assetnum 
LEFT JOIN maximo.BTV_ASSET t3 ON T1.ASSETNUM=t3.ASSETNUM  
WHERE T1.istask='1' 
  AND T1.SITEID='ALBAL' 
  AND T1.STATUS='COMP' 
  AND t2.STATUS='ACTIVE' 
  AND t1.STATUSDATE = TO_DATE(:target_date_str, 'YYYY-MM-DD HH24:MI:SS')
"""

# 执行时传入字符串参数
cursor.execute(sql, [fecha_str])

这里要注意,Oracle的时分秒格式用HH24表示24小时制,MI表示分钟,SS表示秒,别写错成MM(那是月份)。

最后再提个小细节

你原来的SQL里用的是t1.STATUSDATE = 'xxx',如果Oracle的STATUSDATE是datetime字段,而你要匹配的是某一天的所有记录(不是精确到秒的时间点),那应该用范围查询,比如:

AND t1.STATUSDATE BETWEEN :start_date AND :end_date

对应的Python代码就是把当天的0点和次日的0点传进去,这样就能查到当天所有状态日期为COMP的工单了。

备注:内容来源于stack exchange,提问作者Monvana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 14:03:06