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

Python csv_writer如何无需to_char统一格式化Oracle日期列?

解决cx_Oracle日期列批量格式化输出到CSV的问题

你遇到的问题其实是cx_Oracle的默认数据转换行为导致的——当你从Oracle获取DATE类型数据时,驱动会自动把它转换成Python的datetime对象,而不是遵循你设置的会话NLS_DATE_FORMAT格式。所以哪怕你执行了ALTER SESSION,csv_writer在写入时还是会用Python datetime对象默认的字符串格式(也就是你看到的YYYY-MM-DD HH:MM:SS)来输出。

不用每个列都写to_char的话,有两种比较优雅的批量处理方法:

方法1:让cx_Oracle直接返回格式化后的日期字符串

你可以在创建Oracle连接的时候,直接指定nls_date_format参数,这样驱动会把DATE类型的数据直接转换成你想要的格式字符串,而不是datetime对象。修改你的连接代码就行:

import csv
import cx_Oracle

file_handle = open("test.csv", "w")
csv_writer = csv.writer(file_handle, dialect="excel", lineterminator='\n', delimiter=';', quoting=csv.QUOTE_NONNUMERIC)

# 连接时指定NLS_DATE_FORMAT,直接返回格式化后的字符串
conn = cx_Oracle.connect(connectionstring, nls_date_format='DD.MM.YYYY')
cur = conn.cursor()

# 不需要再执行ALTER SESSION语句
cur.execute("select attr4 from aTable")
rows = cur.fetchmany(16000)
while len(rows) > 0:
    csv_writer.writerows(rows)
    rows = cur.fetchmany(16000)

cur.close()
conn.close()
file_handle.close()

这样查询返回的attr4就是直接格式化好的DD.MM.YYYY字符串,写入CSV时就符合你的要求了。如果需要带时间的格式,把nls_date_format改成'DD.MM.YYYY HH24:MI:SS'即可。

方法2:批量转换行中的datetime对象

如果你不想修改连接参数,也可以在写入CSV之前,遍历每一行的数据,把所有datetime类型的元素转换成指定格式的字符串。比如写一个辅助函数来处理行数据:

import csv
import cx_Oracle
from datetime import datetime

def format_datetime_rows(rows, date_format='DD.MM.YYYY'):
    formatted_rows = []
    # 映射Oracle格式到Python的strftime格式
    py_date_format = '%d.%m.%Y'
    if date_format == 'DD.MM.YYYY HH24:MI:SS':
        py_date_format = '%d.%m.%Y %H:%M:%S'
    for row in rows:
        formatted_row = []
        for item in row:
            if isinstance(item, datetime):
                formatted_row.append(item.strftime(py_date_format))
            else:
                formatted_row.append(item)
        formatted_rows.append(formatted_row)
    return formatted_rows

file_handle = open("test.csv", "w")
csv_writer = csv.writer(file_handle, dialect="excel", lineterminator='\n', delimiter=';', quoting=csv.QUOTE_NONNUMERIC)

conn = cx_Oracle.connect(connectionstring)
cur = conn.cursor()
cur.execute("select attr4 from aTable")

rows = cur.fetchmany(16000)
while len(rows) > 0:
    # 先转换日期格式再写入CSV
    formatted_rows = format_datetime_rows(rows)
    csv_writer.writerows(formatted_rows)
    rows = cur.fetchmany(16000)

cur.close()
conn.close()
file_handle.close()

这个方法的好处是可以灵活处理不同的日期格式,甚至同时处理DATE和TIMESTAMP类型的数据,只要是Python的datetime对象都会被统一转换。

补充说明

为什么ALTER SESSION没效果?因为cx_Oracle默认会将Oracle的DATE/TIMESTAMP类型映射为Python的datetime对象,这个转换过程是驱动内部完成的,不会受会话的NLS_DATE_FORMAT影响。只有当你配置驱动返回字符串类型时(比如方法1的设置),NLS格式才会生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:00:56