繁体   English   中英

Select TIMESTAMP(6) WITH TIME ZONE 使用 Pandas、SQLAlchemy 和 cx_Oracle

[英]Select TIMESTAMP(6) WITH TIME ZONE using Pandas, SQLAlchemy and cx_Oracle

我正在尝试使用 pandas 到 select 来自 Oracle 数据库的一些数据。 相关列的数据类型为TIMESTAMP(6) WITH TIME ZONE 我与数据库处于同一时区,但它包含从不同时区记录的数据。

Oracle version: Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
Python 3.8.13
SQLAlchemy 1.4.39
cx_Oracle 8.3.0

在 PL/SQL Developer 中,查询有效:

SELECT col
FROM table

退货

18-JAN-21 09.54.58.000000000 PM ASIA/BANGKOK

在 Python 中,我收到此错误:

import sqlalchemy
import cx_Oracle

server = server
port = port
sid = sid
username = username
password = password
dsn_tns = cx_Oracle.makedsn(server, port, sid)
cnxn = cx_oracle.connect(username, password, dsn_tns)

query = """
    SELECT col
    FROM table
"""
df = pd.read_sql_query(query, cnxn)

Output:

DatabaseError: ORA-01805: possible error in date/time operation

经过一些 SO 搜索,我尝试了这个:

query = """
    SELECT CAST(TO_TIMESTAMP_TZ(
        col, 
        'DD-MMM-YY HH.MI.SS.FF6 TZH TZR')
) AT TIME ZONE 'ASIA/BANGKOK' AS col
    FROM table
"""

df = pd.read_sql_query(query, cnxn_tds_dev)

它返回不同的错误消息:

ORA-00905: missing keyword

我怎样才能使用 Python/SQLAlchemy/cx_Oracle 仅 select 这个时间戳列(以及其他几个)? 因为查询在 PL/SQL Developer 中有效,所以我假设这是 cx_Oracle 的问题。 根据这篇文章,我将尝试使用旧版本的 cx_Oracle 创建一个新的 Python 环境。

作为记录,我在原始评论线程中提到的代码是:

# create table t (c TIMESTAMP(6) WITH TIME ZONE);
# insert into t (c) values (systimestamp);
# commit;
#
# Name: pandas
# Version: 1.5.2
# Name: SQLAlchemy
# Version: 1.4.44
# Name: cx-Oracle
# Version: 8.3.0
#
# Output is like:
#  0 2022-11-24 11:49:25.505773

import os
import platform

from sqlalchemy import create_engine
import pandas as pd

import cx_Oracle

if platform.system() == "Darwin":
    cx_Oracle.init_oracle_client(lib_dir=os.environ.get("HOME")+"/Downloads/instantclient_19_8")

username = os.environ.get("PYTHON_USERNAME")
password = os.environ.get("PYTHON_PASSWORD")
connect_string = os.environ.get("PYTHON_CONNECTSTRING")
hostname, service_name = connect_string.split("/")

engine = create_engine(f'oracle://{username}:{password}@{hostname}/?service_name={service_name}')

query = """select * from t"""
df = pd.read_sql_query(query, engine)
print(df)

一种解决方案是将有问题的列转换为字符串,然后转换为 pandas。

query = "SELECT TO_CHAR(col) AS col FROM table"
df = pd.read_sql_query(query, cnxn)
df[col] = df[col].apply(pd.to_datetime, format="%d-%b-%y %I.%M.%S.%f %p %Z")

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM