Python pandas通过cx_Oracle导入Oracle数据原值丢失问题咨询
问题根源
你遇到的格式丢失问题核心来自两个环节:
- 读取txt文件时Pandas自动做了类型推断,把带前导零的门店号转为整数、金额转为浮点数、日期转为datetime类型,原始字符串格式在读取阶段就已经丢失,后续再转str也无法恢复。
- Oracle表的字段类型和插入逻辑不匹配:数值类型不存储前导零和前缀正负号、DATE类型精度仅到秒、无原生布尔类型会自动转换布尔值的存储格式。
分步解决方案
1. 读取文件阶段固定原始格式
读取txt时强制所有字段为字符串类型,禁止Pandas自动类型推断,从源头保留原始文本的前导零、正负号、日期全量格式、布尔值字符串:
# sep根据你的txt分隔符调整,keep_default_na=False避免Pandas把'NA'等合法值识别为空 df = pd.read_csv("你的txt文件路径.txt", sep="\t", dtype=str, keep_default_na=False)
2. 调整Oracle表字段类型
要完全匹配原始格式,表字段按以下规则设置:
- 日期字段:如果需要保留完整字符串格式设为
VARCHAR2(30),如果需要存储为时间类型设为TIMESTAMP(9)(支持纳秒精度) - STORE、COST字段:设为
VARCHAR2类型,不可设置为NUMBER类型(数值类型会自动丢失前导零和前缀符号) - PARTIAL字段:设为
VARCHAR2(10),不可用布尔/CHAR类型,避免自动转换为F/T
3. 修改插入逻辑用批量绑定执行
替换原有循环单条插入逻辑,用cx_Oracle的executemany批量插入,既提升插入效率(百万条可压缩到5分钟内),也避免单条插入时的隐式类型转换:
import math import cx_Oracle import pandas as pd # 空值预处理,把Pandas空值转为Oracle识别的None processed_data = [] for row in df.values.tolist(): new_row = [] for val in row: if pd.isna(val) or (isinstance(val, float) and math.isnan(val)): new_row.append(None) else: new_row.append(val) processed_data.append(new_row) # 生成插入SQL,用占位符避免SQL注入和类型转换问题 table_name = "你的目标表名" placeholders = ",".join([f":{i+1}" for i in range(len(df.columns))]) insert_sql = f"INSERT INTO {table_name} VALUES({placeholders})" # 批量插入 cur = con.cursor() cur.executemany(insert_sql, processed_data) con.commit() cur.close()
可选:日期存为TIMESTAMP类型的适配方案
如果需要日期字段为时间类型而非字符串,修改插入SQL指定时间格式即可:
# 假设第一列为日期字段,其他字段按顺序占位 insert_sql = f""" INSERT INTO {table_name} VALUES (to_timestamp(:1, 'DD-MON-RR HH.MI.SS.FF9 AM'), :2, :3, :4) """
查询时用to_char(日期字段名, 'DD-MON-RR HH.MI.SS.FF9 AM')即可得到和原始文本完全一致的日期格式。
内容的提问来源于stack exchange,提问作者itskcl
相关产品推荐
相关产品推荐

