【问题标题】:Connecting to an Oracle database using SQLAlchemy使用 SQLAlchemy 连接到 Oracle 数据库
【发布时间】:2015-04-11 18:38:07
【问题描述】:

我能够成功连接到 SQLite 数据库并使用以下命令集访问特定表:

from sqlalchemy import create_engine, MetaData, Table, and_
from sqlalchemy.sql import select
from pandas import DataFrame 

db = create_engine('sqlite:///path\\database.db')
metadata = MetaData(db)
table = Table('table name', metadata, autoload=True)

我可以使用 cx_Oracle 从 Oracle 数据库中获取数据。

但是,当我尝试在 SQLAlchemy 中连接到 Oracle 数据库时,我收到以下错误:

NoSuchTableError:

我使用了以下命令:

db = create_engine('oracle://username:password@hostname:1521/instance name', echo='debug')
md = MetaData(bind=db)
t = Table('table name', md, autoload=True, schema='schema name')

当我使用以下命令时:

t= Table('table name', md, autoload=True, oracle_resolve_synonyms=True)

我收到以下错误:

AssertionError: 架构可见多个表,您必须指定所有者

你能解释一下我到底哪里错了吗?

【问题讨论】:

  • 尝试传递username."table name" 而不是table name。我猜在其他模式中还有另一个同名的表,这个用户也可以访问。

标签: python oracle sqlalchemy


【解决方案1】:

假设你的机器上有一个有效的 tnsnames.ora 文件的 Oracle 客户端,这对我有用:

from sqlalchemy import create_engine
import pandas as pd 
engine = create_engine('oracle://myusername:mypassword@SID')
con = engine.connect()
outpt = con.execute("SELECT * FROM YOUR_TABLE")
df = pd.DataFrame(outpt.fetchall())
df.columns = outpt.keys()
print(df.head())
con.close() 

【讨论】:

  • 使用 tnsnames.ora 连接到 Oracle 没有 sqlalchemy 要求。您可以轻松连接 LDAP、OUD、OID 等。
【解决方案2】:
from sqlalchemy import create_engine
import cx_Oracle

host=hostname
port=port
sid='sid'
user='username'
password='password'
sid = cx_Oracle.makedsn(host, port, sid=sid)

cstr = 'oracle://{user}:{password}@{sid}'.format(
    user=user,
    password=password,
    sid=sid
)

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

result = engine.execute('select * from TABLE')

for row in result:
    print row

这对我有用。也可以像

一样创建连接对象
conn = engine.connect()
conn.close()

这将启用关闭连接。即使您有从本地端口到远程数据库的隧道,这也有效。

【讨论】:

  • 我宁愿从sqlalchemy.engine.url.URL("oracle", user, password, sid)构建它,而不是像cstr那样使用连接字符串
【解决方案3】:

您不再需要导入 cx_Oracle。较新版本的 sqlalchemy 模块调用函数 cx_Oracle.makedsn()。看看:

from sqlalchemy.engine import create_engine

DIALECT = 'oracle'
SQL_DRIVER = 'cx_oracle'
USERNAME = 'your_username' #enter your username
PASSWORD = 'your_password' #enter your password
HOST = 'subdomain.domain.tld' #enter the oracle db host url
PORT = 1521 # enter the oracle port number
SERVICE = 'your_oracle_service_name' # enter the oracle db service name
ENGINE_PATH_WIN_AUTH = DIALECT + '+' + SQL_DRIVER + '://' + USERNAME + ':' + PASSWORD +'@' + HOST + ':' + str(PORT) + '/?service_name=' + SERVICE

engine = create_engine(ENGINE_PATH_WIN_AUTH)


#test query
import pandas as pd
test_df = pd.read_sql_query('SELECT * FROM global_name', engine)

【讨论】:

  • 知道为什么我不断收到错误,例如:“NoSuchModuleError: Can't load plugin: sqlalchemy.dialects:oracle.cx_oracle”?
  • @Konstantin 您在使用虚拟环境吗?我会安装 cx_oracle 以确保:python -m pip install cx_Oracle --upgrade
  • 我在使用这种方法时遇到了错误。这是他们最近在 oracle 中更改的内容吗?在他们的博客中,他们只显示了一种方法,您需要使用 wallet.sso 文件..
  • @RicardoSampaio 能否请您发布错误消息。以及您尝试访问的 oracle db 版本?我目前只使用 Athena 和 MS SQL。所以我不知道如何重现它,但让我试试。
【解决方案4】:

当没有tnsnames.ora 文件时,这对我有用。

user = 'system'
pwd = 'oracle'
dsn = cx_Oracle.makedsn(
    '192.168.1.105', 49161,
    # service_name='your_service_name_if_any'
)
ora_engine = create_engine(f'oracle+cx_oracle://{user}:{pwd}@{dsn}', echo=True)
ora_engine.connect()

【讨论】:

    【解决方案5】:

    这是@mkarun2 答案的略微完善的版本。

    先决条件:

    • 安装包:

      sudo apt install libaio1

    • 下载 Oracle InstantClient 库

    • 创建符号链接:

      ln -s libclntsh.so.21.1 libclntsh.so

    • 像这样运行应用程序:

      导出 LD_LIBRARY_PATH=oracle-instantclient/instantclient_21_1 python main.py

    这是main.py:

    import cx_Oracle
    import sqlalchemy as sa
    
    
    # Use your config
    username = 'username'
    password = 'security'
    hostname = 'localhost'
    service_name = 'Xal' or None
    port = '1521'
    
    
    # Tell cx_Oracle where to find the libraries. Optional.
    cx_Oracle.init_oracle_client(lib_dir='oracle-instantclient/instantclient_21_1')
    
    
    # Connection string
    oracle_connection_string_fmt = (
        'oracle+cx_oracle://{username}:{password}@' +
        cx_Oracle.makedsn('{hostname}', '{port}', service_name='{service_name}')
    )
    url = oracle_connection_string_fmt.format(
        username=username, password=password, 
        hostname=hostname, port=port, 
        service_name=service_name,
    )
    
    # Create SqlAlchemy Engine
    engine: sa.engine.Engine = sa.create_engine(url, echo=True)
    

    这是进行第一个查询的方法:

    res: sa.engine.cursor.LegacyCursorResult = engine.execute("SELECT * FROM tablename")
    for row in res:
        print(row)
    

    注意查询的末尾没有; ;) Oracle 不喜欢分号。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-05
      • 1970-01-01
      • 2020-10-27
      • 2018-03-26
      • 1970-01-01
      • 2012-04-11
      • 2011-11-12
      • 2017-04-06
      相关资源
      最近更新 更多