pandas read_sql读取Oracle正常但to_sql报ORA-00904无效标识符错误
错误根因分析
to_sql参数使用错误:你将schema名NCSUSR和表名COLL_CLIENT_SUBMISSION_DTLS拼接后作为第一个参数传入,SQLAlchemy会将整段字符串识别为表名,生成SQL时自动添加双引号包裹,导致Oracle无法正确解析schema和表的对应关系。- 字段名大小写不匹配:Oracle默认将未加双引号的标识符转为大写存储,
read_sql返回的DataFrame列名如果为小写格式,to_sql生成插入语句时直接使用小写列名,会触发大小写匹配失败的无效标识符错误。 - 补充:代码中异常捕获的
exception未大写,会额外触发NameError报错。
修复后代码
from sqlalchemy import create_engine,types import cx_Oracle import pandas as pd import time ip = '192.168.213.151' port = 1515 SID = 'abc' User='abc' pwd ='abc' dsn_tns = cx_Oracle.makedsn(ip, port, SID) # 增加arraysize参数提升批量写入性能 engine = create_engine('oracle+cx_oracle://%s:%s@%s' % (User, pwd, dsn_tns), arraysize=10000) def InsertIntoDB(): try: conn = engine.connect() FinalDataframe = pd.read_sql('select * from NCSUSR.COLL_CLIENT_SUBMISSION_DTLS', conn) # 列名转大写,匹配Oracle字段命名规则 FinalDataframe.columns = [col.upper() for col in FinalDataframe.columns] start_time = time.time() # 拆分schema和表名参数,避免标识符识别错误 FinalDataframe.to_sql( name='COLL_CLIENT_SUBMISSION_DTLS', schema='NCSUSR', con=conn, index=False, if_exists='append', chunksize=10**4 ) print("--- %s seconds ---" % (time.time() - start_time)) print("successful") conn.close() except Exception as ex : print(ex) InsertIntoDB()
50万行数据写入优化建议
- 现有
chunksize=10**4的配置可平衡内存占用和写入效率,无需调整,避免单次提交数据量过大导致内存溢出。 - 写入前可暂时禁用目标表的非必要索引、触发器,写入完成后再重建,可将写入速度提升3-10倍。
- 若为全量覆盖写入场景,可将
if_exists参数临时改为replace先删表重建再写入,进一步提升速度,增量写入场景不要修改该参数。
内容的提问来源于stack exchange,提问作者Alok Sharma
相关产品推荐
相关产品推荐

