cx_Oracle使用executemany()插入日期时间报ORA-01861解决方法
cx_Oracle executemany批量插入Date/Datetime类型避免ORA-01861错误方案
ORA-01861错误的核心触发原因是日期/时间类型的传值和Oracle端格式解析规则不匹配,结合你提供的代码,除了格式问题外还存在多处基础语法错误,以下是可直接运行的修正方案和避坑规则。
原代码存在的显性问题
- 拼写/语法错误:
pd.dataframe应为pd.DataFrame,cx_Orace.connet应为cx_Oracle.connect,Tuple应为Python内置类型tuple,循环中构造的参数元组未追加到data列表,实际传入executemany的是空列表 - 日期构造错误:
datetime.date(df['dt'][ind])写法错误,datetime.date类要求传入年、月、日三个整数参数,直接传入字符串会生成非法对象 - SQL写法错误:表中
id是自增主键共4个字段,你写的插入语句仅传3个值且未指定对应字段名,会触发字段数量/顺序匹配错误 - 类型依赖隐式转换:直接传字符串给日期字段时,Oracle会用会话级
NLS_DATE_FORMAT/NLS_TIMESTAMP_FORMAT配置解析字符串,格式不匹配就会抛ORA-01861
修正后可运行代码
import cx_Oracle import pandas as pd from datetime import datetime, date apiToDf = { 'strMsg': ['AA', 'BB', 'CC', 'DD'], 'dt': ['2022-02-01', '2022-02-02', '2022-02-03', '2022-02-04'] } df = pd.DataFrame(apiToDf) data = [] PROCESS_TIME = datetime.now() # 构造批量参数列表 for ind in df.index: # 按固定格式将字符串解析为Python原生date对象,禁止直接传字符串给Oracle dt_value = datetime.strptime(df['dt'][ind], "%Y-%m-%d").date() # 参数顺序和SQL中绑定变量顺序严格对应 param = ( df['strMsg'][ind], dt_value, PROCESS_TIME ) data.append(param) conn = cx_Oracle.connect('Test', '123456', '127.0.0.1/testDb') cursor = conn.cursor() target_tb = 'test_db' # 显式指定插入字段,避开自增主键列,避免字段顺序/数量匹配错误 script = """ INSERT INTO {tb} (strMsg, dt, dt_time) VALUES (:1, :2, :3) """.format(tb=target_tb) try: # 可选:显式指定绑定变量类型,100%避免类型自动识别偏差 cursor.setinputsizes( cx_Oracle.STRING, cx_Oracle.DATETIME, cx_Oracle.TIMESTAMP ) cursor.executemany(script, data) conn.commit() except Exception as e: conn.rollback() raise e finally: cursor.close() conn.close()
核心避坑规则
- 禁止传日期字符串给Oracle解析:所有日期、时间参数必须在Python端转为原生
datetime.date/datetime.datetime对象,cx_Oracle会自动完成类型适配,完全不依赖Oracle端NLS格式配置,从根源上杜绝ORA-01861 - 必须显式写插入字段名:表存在自增列、默认值列时,绝对不能省略
INSERT INTO后的字段列表,否则会按表结构默认顺序匹配值,触发类型或数量错误 - 空值处理规范:日期字段需要传空时,传入Python的
None即可,不要传空字符串、'null'等非法值 - 参数列表校验:循环构造完参数后,可先打印
data长度和单元素结构,确认参数已正确追加、每个元组的元素数量和类型符合预期
内容的提问来源于stack exchange,提问作者W Kenny
相关产品推荐
相关产品推荐

