在 Python 中使用 ODBC 连接到 Oracle
Connect to Oracle with ODBC in Python
我成功安装了 Oracle 12.2.01,运行 它的官方 Docker image 在 64 位 Linux 上:
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、端口……None 以下作品:
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 术语一头雾水(您需要多少 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
不需要。
不需要创建额外 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', )]
我成功安装了 Oracle 12.2.01,运行 它的官方 Docker image 在 64 位 Linux 上:
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、端口……None 以下作品:
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 术语一头雾水(您需要多少 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
不需要。
不需要创建额外 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', )]