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

使用SQLAlchemy连接Oracle时遭遇ORA-12505错误求助

解决SQLAlchemy连接Oracle时的ORA-12505错误

问题背景

尝试通过依赖cx_Oracle的SQLAlchemy实现Python与Oracle数据库的连接,后续计划将代码用于LangChain对接OpenAI,但运行代码时触发ORA-12505错误。已确认可通过sqlplus以SCOTT用户成功连接orclpdb实例,但执行Python代码时失败。

现有代码与连接信息

app.py代码

from sqlalchemy import create_engine
import cx_Oracle
import config

sid = cx_Oracle.makedsn(config.DATABASE['host'], config.DATABASE['port'], sid=config.DATABASE['database'])

cstr = '{drivername}://{user}:{password}@{sid}'.format(
    drivername = config.DATABASE['drivername'],
    user=config.DATABASE['username'],
    password=config.DATABASE['password'],
    sid=sid
)

engine =  create_engine(
    cstr,
#    convert_unicode=False,
    pool_recycle=10,
    pool_size=50,
    echo=True
)

stmt = 'select * from emp'
with engine.connect() as conn:
     result = conn.execute(stmt)

for row in result:
    print(row)

config.py代码

DATABASE = {
'drivername' : 'oracle',
'host'        : '192.168.1.3',
'port'        : '1521',
'database'    :'orclpdb',
'username'    :'scott',
'password'    :'tiger'
}

成功的sqlplus连接示例

C:\Users\HI\Desktop\New folder>sqlplus scott/tiger@//DESKTOP-CKEA6JR:1521/orclpdb
SQL*Plus: Release 21.0.0.0.0 - Production on Thu Mar 7 15:22:24 2024
Version 21.3.0.0.0
Copyright (c) 1982, 2021, Oracle.  All rights reserved.
Last Successful login time: Thu Mar 07 2024 14:55:54 +05:30
Connected to:
Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
SQL> sho con_name
CON_NAME
------------------------------
ORCLPDB
SQL>
SQL> alter system register;
System altered.

执行命令

C:\Users\HI\AppData\Local\Programs\Python\Python312\python.exe app.py

问题原因

ORA-12505错误是由于监听无法识别请求中的SID。观察成功的sqlplus连接使用的是服务名格式(//主机:端口/服务名),但代码中使用cx_Oracle.makedsn时传入的是sid参数,而orclpdb作为可插拔数据库(PDB),通常使用服务名而非SID作为连接标识。

解决方案

提供两种修改方式,任选其一即可:

方式一:直接构造服务名格式的连接串

放弃使用cx_Oracle.makedsn,直接按照sqlplus的连接格式构造字符串:

from sqlalchemy import create_engine
import config

# 直接构造服务名格式的连接串
cstr = '{drivername}://{user}:{password}@{host}:{port}/{database}'.format(
    drivername=config.DATABASE['drivername'],
    user=config.DATABASE['username'],
    password=config.DATABASE['password'],
    host=config.DATABASE['host'],
    port=config.DATABASE['port'],
    database=config.DATABASE['database']
)

engine = create_engine(
    cstr,
    pool_recycle=10,
    pool_size=50,
    echo=True
)

stmt = 'select * from emp'
with engine.connect() as conn:
     result = conn.execute(stmt)

for row in result:
    print(row)

方式二:修改makedsn参数为service_name

如果需要继续使用cx_Oracle.makedsn,将参数从sid改为service_name:

from sqlalchemy import create_engine
import cx_Oracle
import config

# 使用service_name参数指定PDB服务名,而非sid
sid = cx_Oracle.makedsn(config.DATABASE['host'], config.DATABASE['port'], service_name=config.DATABASE['database'])

cstr = '{drivername}://{user}:{password}@{sid}'.format(
    drivername=config.DATABASE['drivername'],
    user=config.DATABASE['username'],
    password=config.DATABASE['password'],
    sid=sid
)

engine = create_engine(
    cstr,
    pool_recycle=10,
    pool_size=50,
    echo=True
)

stmt = 'select * from emp'
with engine.connect() as conn:
     result = conn.execute(stmt)

for row in result:
    print(row)

说明

可插拔数据库(PDB)的SID通常与容器数据库(CDB)一致,而服务名是PDB的专属标识。代码需与sqlplus的连接方式保持一致,使用服务名才能正确连接到目标PDB实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 09:43:11