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

Python向Oracle插入数据遇DPY-4004错误,如何修改DataFrame解决?

解决Oracle插入MRCONSO表时的DPY-4004无效数字错误

问题背景

我用Python脚本创建Oracle的MRCONSO表,代码如下:

cur.execute('''BEGIN EXECUTE IMMEDIATE 'DROP TABLE MRCONSO'; 
               EXCEPTION WHEN OTHERS THEN NULL; 
               END;
            ''')

try:
    cur.execute('''
                CREATE TABLE MRCONSO (
                CUI char(8) NOT NULL,
                LAT char(3) NOT NULL,
                TS char(1) NOT NULL,
                LUI varchar2(10) NOT NULL,
                STT varchar2(3) NOT NULL,
                SUI varchar2(10) NOT NULL,
                ISPREF char(1) NOT NULL,
                AUI varchar2(9) NOT NULL,
                SAUI integer,
                SCUI varchar2(100),
                SDUI varchar2(100),
                SAB varchar2(40) NOT NULL,
                TTY varchar2(40) NOT NULL,
                CODE varchar2(100) NOT NULL,
                STR varchar2(3000) NOT NULL,
                SRL integer NOT NULL,
                SUPPRESS char(1) NOT NULL,
                CVF integer)
                PCTFREE 10 PCTUSED 80
                '''
               )
    
    print("MRCONSO Table Created")
                
except Exception as e:
    print("Error: ",str(e))

插入CSV数据时触发错误:

Oracle error message: DPY-4004: invalid number

数据处理代码:

df_umls = pd.read_csv("../umls_files/umls-2023AA-metathesaurus-full/2023AA/META/MRCONSO.RRF", sep = '|', low_memory=False)
df_umls.columns=["CUI", "LAT", "TS", "LUI", "STT", "SUI", "ISPREF", "AUI","SAUI", "SCUI", "SDUI", "SAB", "TTY", "CODE", "STR", "SRL", "SUPPRESS", "CVF", "JUNK"]
df_umls = df_umls.drop(columns=['JUNK'])

df_umls['CVF'] = df_umls['CVF'].fillna(0) 
df_umls['CVF'] = df_umls['CVF'].astype("Int64") 

df_umls['SAUI'] = df_umls['SAUI'].fillna(0) 
df_umls['SAUI'] = df_umls['SAUI'].astype("Int64") 


try:
    if conn:
        print("Oracle version:", oracledb.version)
        print("Database version:", conn.version)
        #print("Client version:", oracledb.clientversion())
        print('Inserting data into table....')
        for i,row in tqdm(df_umls.iterrows(), total=df_umls.shape[0]):
            sql_conso = "insert into MRCONSO (CUI,LAT,TS,LUI,STT,SUI,ISPREF, AUI, SAUI, SCUI, SDUI, SAB, TTY, CODE, STR, SRL, SUPPRESS, CVF) values (:0,:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16,:17)"
            cur.execute(sql_conso, tuple(row))
        # the connection is not autocommitted by default, so we must commit to save our changes
        conn.commit()
        print("Record inserted succesfully")
except DatabaseError as e:
    err, = e.args
    print("Oracle-Error-Code:", err.code)
    print("Oracle-Error-Message:", err.message)
finally:
    cur.close()
    conn.close()

当前DataFrame的数据类型:

CUI object
LAT object
TS object
LUI object
STT object
SUI object
ISPREF object
AUI object
SAUI Int64
SCUI object
SDUI object
SAB object
TTY object
CODE object
STR object
SRL int64
SUPPRESS object
CVF Int64
dtype: object

解决方法

DPY-4004错误是因为Oracle无法将某些值转换为整数类型,重点检查SAUI、CVF、SRL这三个整数类型字段,按以下步骤修改DataFrame:

1. 彻底清理非数字值

原始数据中可能存在空字符串、空格或其他非数字字符,仅用fillna无法处理这些情况,需用pd.to_numeric强制转换并过滤无效值:

# 处理SAUI:将非数字值转为NaN,再填充0后转整数类型
df_umls['SAUI'] = pd.to_numeric(df_umls['SAUI'], errors='coerce').fillna(0).astype('Int64')
# 处理CVF:同理
df_umls['CVF'] = pd.to_numeric(df_umls['CVF'], errors='coerce').fillna(0).astype('Int64')
# 处理SRL:确保无无效值
df_umls['SRL'] = pd.to_numeric(df_umls['SRL'], errors='coerce').fillna(0).astype('int64')

2. 兼容Oracle整数类型(可选)

Pandas的Int64是可空整数类型,部分场景下可能和Oracle的integer类型存在转换冲突,可尝试转为普通int类型:

df_umls['SAUI'] = df_umls['SAUI'].fillna(0).astype(int)
df_umls['CVF'] = df_umls['CVF'].fillna(0).astype(int)

3. 定位错误行(调试用)

如果仍报错,可以在插入循环中加入异常捕获,定位具体出错的行,针对性处理:

for i,row in tqdm(df_umls.iterrows(), total=df_umls.shape[0]):
    try:
        cur.execute(sql_conso, tuple(row))
    except DatabaseError as e:
        print(f"错误行索引:{i},数据内容:{row}")
        raise e

4. 批量插入优化(推荐)

逐行插入效率极低,建议用to_sql批量插入,同时指定字段类型映射避免转换问题:

from sqlalchemy import create_engine
# 创建Oracle连接引擎,替换为你的连接信息
engine = create_engine('oracle+oracledb://用户名:密码@主机:端口/服务名')
# 定义字段与Oracle类型的映射
dtype = {
    'CUI': 'CHAR(8)',
    'LAT': 'CHAR(3)',
    'TS': 'CHAR(1)',
    'LUI': 'VARCHAR2(10)',
    'STT': 'VARCHAR2(3)',
    'SUI': 'VARCHAR2(10)',
    'ISPREF': 'CHAR(1)',
    'AUI': 'VARCHAR2(9)',
    'SAUI': 'INTEGER',
    'SCUI': 'VARCHAR2(100)',
    'SDUI': 'VARCHAR2(100)',
    'SAB': 'VARCHAR2(40)',
    'TTY': 'VARCHAR2(40)',
    'CODE': 'VARCHAR2(100)',
    'STR': 'VARCHAR2(3000)',
    'SRL': 'INTEGER',
    'SUPPRESS': 'CHAR(1)',
    'CVF': 'INTEGER'
}
# 批量插入,chunksize可根据内存调整
df_umls.to_sql('MRCONSO', engine, if_exists='append', index=False, dtype=dtype, chunksize=1000)

内容的提问来源于stack exchange,提问作者rshar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 14:49:53