Flask+SQLAlchemy连接Oracle时ORA-01843无效月份错误求助
ORA-01843: not a valid month 错误在Flask+SQLAlchemy+Oracle部署环境中出现(本地正常)
我用Flask框架结合SQLAlchemy查询Oracle数据库开发Web应用,本地用Flask内置服务器运行完全正常,但部署到正式服务器后——哪怕同样用Flask开发服务器跑——就出现ORA-01843: not a valid month错误。两个环境的Oracle客户端版本一致,怀疑是客户端配置的问题。我在Flask Shell里执行同样的查询,也会报相同的错。
查询代码如下:
query = db.session.query(intervaldate.TSTART,kpi_db.VALUE) query = query.filter(intervaldate.ID == kpi_db.INTERVAL_ID) query = query.filter(intervaldate.TSTART>=t_ini) query = query.filter(intervaldate.TSTART<=t_end) query = query.filter(kpi_db.KPI_ID==1) query = query.filter(kpi_db.CTRL_ID==ctrl_id) query = query.all()
网上说可以在会话里设置NLS_TIMESTAMP_FORMAT解决,但不知道具体怎么操作。有没有人遇到过SQLAlchemy下的这类问题?
解决方法:设置Oracle会话的NLS参数
这个问题大概率是正式服务器的Oracle客户端默认日期/时间戳格式,和TSTART字段类型、或你传入的t_ini/t_end格式不兼容导致的。在SQLAlchemy里可以通过两种方式设置会话级NLS参数:
方法1:每次查询前手动设置会话参数
在执行目标查询前,先执行ALTER SESSION语句指定对应格式:
from sqlalchemy import text # 先设置会话参数,格式需匹配TSTART字段类型和传入参数格式 db.session.execute(text("ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS'")) db.session.execute(text("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD'")) # 再执行原查询 query = db.session.query(intervaldate.TSTART,kpi_db.VALUE) # ... 后续查询代码不变
注意:如果TSTART是DATE类型就用NLS_DATE_FORMAT,是TIMESTAMP类型就用NLS_TIMESTAMP_FORMAT,格式字符串要和数据库字段、传入的时间参数格式完全对应。
方法2:通过SQLAlchemy事件自动设置会话参数
如果不想每次查询都手动执行设置,可以用after_begin事件,在每次会话创建时自动配置参数:
from sqlalchemy import event from your_app import db @event.listens_for(db.session, 'after_begin') def set_nls_parameters(session, transaction, connection): connection.execute(text("ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS'")) connection.execute(text("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD'"))
把这段代码放在Flask应用初始化的位置(比如app/__init__.py),后续所有会话都会自动应用这些参数。
额外检查点
- 确保
t_ini和t_end是Python的datetime对象而非字符串,避免格式解析问题:from datetime import datetime t_ini = datetime.strptime("2024-01-01 00:00:00", "%Y-%m-%d %H:%M:%S") t_end = datetime.strptime("2024-01-31 23:59:59", "%Y-%m-%d %H:%M:%S") - 检查正式服务器的
NLS_LANG环境变量,确保和本地配置一致。Linux下执行echo $NLS_LANG,Windows下执行echo %NLS_LANG%即可查看。
内容的提问来源于stack exchange,提问作者Dariva
相关产品推荐
相关产品推荐

