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

SQLAlchemy/oracledb/cx_Oracle插入Timestamp被截断至秒的解决求助

问题描述

需要将包含pandas._libs.tslibs.timestamps.Timestamp类型数据的DataFrame合并到Oracle数据库,DataFrame示例如下:

import pandas as pd
my_test_date = pd.to_datetime(1674009901958454, unit='us')

df = pd.DataFrame(data = {'payment_id_pay': [1, 2],
                          'DT_START': [my_test_date, my_test_date],
                          'DT_END': [my_test_date, my_test_date]})

通过SQLAlchemy执行合并后,数据库中Timestamp字段的毫秒/微秒部分被截断,仅保留到秒(毫秒部分显示为000000)。已尝试纯cx_Oracle、纯oracledb、SQLAlchemy调用setinputsizes,以及将Timestamp转换为datetime.datetime,均未解决问题。

使用版本:SQLAlchemy 2.0.25、oracledb 1.4.2、cx-Oracle 8.3.0;数据库:Oracle Database 19c Enterprise Edition。

请问如何实现不截断时间精度的插入?

解决方案

以下几种方法可解决时间精度被截断的问题:

1. 确认Oracle表字段的精度支持

Oracle的DATE类型仅保留到秒,必须确保目标表的DT_START、DT_END字段类型为TIMESTAMP(6)(默认支持微秒)或TIMESTAMP(9)(Oracle 19c最高精度,支持纳秒),而非DATE类型。

2. SQLAlchemy映射类显式指定TIMESTAMP精度

在定义数据模型时,明确指定日期字段的类型和精度,让SQLAlchemy按高精度传递数据:

from sqlalchemy import Column, Integer, TIMESTAMP
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Payment(Base):
    __tablename__ = 'your_target_table'
    payment_id_pay = Column(Integer, primary_key=True)
    DT_START = Column(TIMESTAMP(precision=6))
    DT_END = Column(TIMESTAMP(precision=6))

使用该模型执行插入/合并操作时,会自动保留微秒精度。

3. oracledb显式指定绑定变量类型

直接使用oracledb操作时,通过setinputsizes强制指定字段为TIMESTAMP类型:

import oracledb

# 建立数据库连接
conn = oracledb.connect(user="your_user", password="your_pwd", dsn="your_dsn")
cursor = conn.cursor()

# 准备待插入数据
data = [(1, my_test_date, my_test_date), (2, my_test_date, my_test_date)]

# 显式指定时间字段的类型
cursor.setinputsizes(None, oracledb.DB_TYPE_TIMESTAMP, oracledb.DB_TYPE_TIMESTAMP)
cursor.executemany("INSERT INTO your_target_table (payment_id_pay, DT_START, DT_END) VALUES (:1, :2, :3)", data)

conn.commit()
cursor.close()
conn.close()

4. 转换为带微秒的字符串插入

将DataFrame中的Timestamp转换为包含微秒的标准时间字符串,直接以字符串形式插入,Oracle会自动解析为高精度TIMESTAMP:

# 转换时间字段为带微秒的字符串格式
df['DT_START'] = df['DT_START'].dt.strftime('%Y-%m-%d %H:%M:%S.%f')
df['DT_END'] = df['DT_END'].dt.strftime('%Y-%m-%d %H:%M:%S.%f')

# 使用to_sql插入数据
df.to_sql('your_target_table', con=engine, if_exists='append', index=False)

此方法需确保目标表字段为TIMESTAMP类型,否则字符串无法正确解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 17:05:20