使用Python向Oracle插入Excel数据时遇类型及执行错误求助
解决Python向Oracle插入Excel数据的常见问题
一、executemany()报TypeError的解决方法
错误提示“参数应为序列/字典列表”,本质是传入的DataFrame数据格式不符合Oracle游标的要求,只需把DataFrame转换成executemany可识别的元组列表或字典列表即可:
- 转元组列表:适合插入语句用位置参数的场景
- 转字典列表:适合插入语句用命名参数的场景
示例代码:
import cx_Oracle import pandas as pd # 读取Excel到DataFrame df = pd.read_excel('data.xlsx') # 连接Oracle conn = cx_Oracle.connect('用户名/密码@主机:端口/服务名') cursor = conn.cursor() # 方法1:元组列表(对应位置参数) insert_sql = "INSERT INTO YOUR_TABLE (COL1, COL2, DATE_COL) VALUES (:1, :2, :3)" data_tuples = [tuple(row) for row in df.itertuples(name=None)] cursor.executemany(insert_sql, data_tuples) # 方法2:字典列表(对应命名参数) insert_sql = "INSERT INTO YOUR_TABLE (COL1, COL2, DATE_COL) VALUES (:COL1, :COL2, :DATE_COL)" data_dicts = df.to_dict('records') cursor.executemany(insert_sql, data_dicts) # 必须提交事务 conn.commit() cursor.close() conn.close()
注:DataFrame中的None值会被cx_Oracle自动转为Oracle的NULL,无需额外处理。
二、to_sql()的类型不匹配与无更新问题解决
1. 日期类型不匹配(expected DATE got CLOB)
问题源于pandas默认将日期列映射为CLOB类型,需手动指定Oracle对应的DATE类型,用sqlalchemy的types.DATE做映射:
from sqlalchemy import create_engine, types import pandas as pd # 创建Oracle连接引擎(格式:oracle+cx_oracle://用户名:密码@主机:端口/?service_name=服务名) engine = create_engine('oracle+cx_oracle://user:pwd@host:1521/?service_name=ORCL') # 定义列类型映射:指定日期列为Oracle DATE类型 dtype_mapping = { 'DATE_COL': types.DATE, # 其他列可按需指定,比如数字列用types.NUMBER } # 执行插入 df.to_sql( name='YOUR_TABLE', con=engine, if_exists='append', index=False, dtype=dtype_mapping )
2. 无报错但数据库无更新
通常是事务未提交或插入条件不满足:
- 手动控制事务:用
with engine.begin() as conn:自动提交事务,避免遗漏提交with engine.begin() as conn: df.to_sql( name='YOUR_TABLE', con=conn, if_exists='append', index=False, dtype=dtype_mapping ) - 检查
if_exists参数:确保用'append'(追加)或'replace'(覆盖),而非'fail'(表存在则跳过) - 校验列名匹配:Oracle默认列名大写,若DataFrame列名是小写,需转为大写或在to_sql中指定
lowercase=False - 排查约束冲突:若表有主键/唯一约束,数据冲突会导致插入失败但无报错,可提前校验数据或查看数据库日志
三、完整可运行示例(Excel读取+插入)
import pandas as pd from sqlalchemy import create_engine, types # 1. 读取Excel数据 df = pd.read_excel('your_data.xlsx') # 2. 预处理日期列(确保为datetime/date类型) df['DATE_COL'] = pd.to_datetime(df['DATE_COL']).dt.date # 3. 创建Oracle连接 engine = create_engine('oracle+cx_oracle://your_username:your_password@your_host:1521/?service_name=your_service') # 4. 定义类型映射 dtype = { 'DATE_COL': types.DATE, 'NUM_COL': types.NUMBER(precision=10, scale=2), 'VARCHAR_COL': types.VARCHAR(length=50) } # 5. 分批插入并自动提交事务 with engine.begin() as conn: df.to_sql( name='TARGET_TABLE', con=conn, if_exists='append', index=False, dtype=dtype, chunksize=1000 # 大数据量时分批插入,避免内存溢出 ) print("数据插入完成")
内容的提问来源于stack exchange,提问作者Benjamin Diaz
相关产品推荐
相关产品推荐

