【问题标题】:Connect to Oracle with ODBC in Python在 Python 中使用 ODBC 连接到 Oracle
【发布时间】:2019-08-20 21:25:06
【问题描述】:

我设法安装了 Oracle 12.2.01,在 64 位 Linux 上运行其官方 Docker image

docker run --name oracle12-se2 -p 1521:1521 -p 5500:5500 -e ORACLE_PWD=my_pwd oracle/database:12.2.0.1-se2

数据库似乎运行正常,我可以输入它的SQL > 提示符:

docker exec -ti oracle12-se2 sqlplus system@ORCLPDB1

并在那里发出命令。

但尝试通过 Python 的 pyodbc 从另一台 Linux 机器连接失败。我正在使用官方的 Oracle Instant Client + ODBC 驱动程序 19.3,但我迷失了所有的首字母缩略词:DBQ、SID、DSN、TSN、实例、SERVER_NAME、tnsnames.ora、端口……以下都不起作用:

import pyodbc  # version 4.0.26
conn_params = [
    {'server': '175.201.160.29:1521', 'uid': 'system', 'pwd': 'my_pwd', 'driver': "Oracle 19 ODBC driver"},
    {'server': '175.201.160.29:1521/ORCLCDB', 'uid': 'system', 'pwd': 'my_pwd', 'driver': "Oracle 19 ODBC driver"},
    {'server': '175.201.160.29:1521/ORCLPDB1', 'uid': 'system', 'pwd': 'my_pwd', 'driver': "Oracle 19 ODBC driver"},
    {'dbq': '175.201.160.29:1521', 'uid': 'system', 'pwd': 'my_pwd', 'driver': "Oracle 19 ODBC driver"},
    {'dbq': '175.201.160.29:1521/ORCLCDB', 'uid': 'system', 'pwd': 'my_pwd', 'driver': "Oracle 19 ODBC driver"},
    {'dbq': '175.201.160.29:1521/ORCLPDB1', 'uid': 'system', 'pwd': 'my_pwd', 'driver': "Oracle 19 ODBC driver"},
]
for attempt in conn_params:
    try:
        conn = pyodbc.connect(**attempt)
        print('SUCCESS!')
    except Exception:
        print('failed with', attempt)

错误总是Error: ('IM004', "[IM004] [unixODBC][Driver Manager]Driver's SQLAllocHandle on SQL_HANDLE_HENV failed (0) (SQLDriverConnect)")。如何调试?


编辑:我取得了一些进展。我可以使用cx-oracle 而不是pyodbc 成功连接到远程数据库:

import cx_Oracle
connection = cx_Oracle.connect("system", "my_pwd", "175.201.160.29/ORCLPDB1")
# …connection cursors work as expected, all good

我想这可以验证数据库或连接本身没有问题。但是,我需要pyodbc 才能工作,而不是cx-oracle,所以我上面的问题仍然存在。

【问题讨论】:

  • Oracle ODBC documentation 表示您需要创建一个 ["tnsnames.ora" 文件]。你考虑过这样做吗?
  • @GordThompson 我运行了提供的odbc_update_ini.sh 并符号链接了所有共享库。我从哪里得到这个tnsnames.ora,我在里面放了什么,之后如何配置pyodbc?官方文档对我来说完全不透明。
  • The Oracle documentation 说,通过使用 Oracle 网络配置助手 (NETCA),您可以在 tnsnames.ora 文件中为每个 TNS 服务名称创建一个条目。安装 Oracle 网络服务时会安装 NETCA ."。失败的是还有一个 dba.stackexchange.com question 谈论它。
  • 不知道 NETCA 是什么,但我手动创建了 tsnnames.ora 文件。它似乎工作。我会把它作为答案发布,看看它是否有意义或者我完全关闭了。

标签: oracle odbc pyodbc


【解决方案1】:

我对所有 Oracle 术语仍然一头雾水(您需要多少 BS 才能连接到数据库?),但以下似乎可行:

$ # on the machine with pyodbc
$ export ORACLE_HOME=/opt/oracle/instantclient_19_3
$ cat $ORACLE_HOME/network/admin/tnsnames.ora

LISTENER = (ADDRESS=(PROTOCOL=tcp)(HOST=175.201.160.29)(PORT=1521))

test=
 (DESCRIPTION=
   (ADDRESS=(PROTOCOL=tcp)(HOST=175.201.160.29)(PORT=1521))
   (CONNECT_DATA=(SERVICE_NAME=ORCLCDB)))

然后从 Python:

>>> import pyodbc
>>> conn = pyodbc.connect(**{'DBQ': 'test', 'uid': 'system', 'pwd': 'my_pwd', 'driver': "Oracle 19 ODBC driver"})
>>> list(conn.cursor().execute("""select * from global_name"""))
[('ORCLCDB', )]

不知道为什么pyodbc 需要该文件而cx-oracle 不需要。

【讨论】:

【解决方案2】:

不需要创建额外的tnsnames.ora 文件的解决方案:

import pyodbc

conn = pyodbc.connect(**{'DBQ': '175.201.160.29/ORCLPDB1', 'uid': 'system', 'pwd': 'my_pwd', 'driver': "Oracle 19 ODBC driver"})
print(list(conn.cursor().execute("""select * from global_name""")))

[('ORCLCDB', )]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多