cx_Oracle не подключается при использовании SID вместо имени службы в строке подключения
У меня есть строка подключения, которая выглядит так:
con_str = "myuser/[email protected]:1521/ora1"
Где ora1
- SID моей базы данных. Использование этой информации в SQL Developer отлично работает, что означает, что я могу подключаться и запрашивать без проблем.
Однако, если я попытаюсь подключиться к Oracle с помощью этой строки, это не сработает.
cx_Oracle.connect(con_str)
DatabaseError: ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
Этот формат строки соединения работает, если ora1
является именем службы.
Я видел другие вопросы, которые, похоже, обращаются к моей проблеме (он работает с SID, но не с именем службы)
Каким образом можно подключиться к Oracle, используя cx_Oracle
, используя SID
а не имя службы? Как это сделать без необходимости корректировки файла TNSNAMES.ORA
? Мое приложение распространено среди многих пользователей внутри страны, и внесение изменений в файл TNSNAMES
является менее идеальным при работе с пользователями без прав администратора на их машинах Windows. Кроме того, когда я использую имя службы, мне не нужно вообще прикасаться к этому файлу и хотелось бы, чтобы он поддерживал его таким образом.
Ответы
Ответ 1
Я похож на сценарий, мне удалось подключиться к базе данных с помощью cx_Oracle.makedsn()
для создания строки dsn с заданным SID
(вместо имени службы):
dsnStr = cx_Oracle.makedsn("oracle.sub.example.com", "1521", "ora1")
Это возвращает что-то вроде
(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=oracle.sub.example.com)(PORT=1521)))(CONNECT_DATA=(SID=ora1)))
который затем можно использовать с cx_Oracle.connect()
для подключения к базе данных:
con = cx_Oracle.connect(user="myuser", password="mypass", dsn=dsnStr)
print con.version
con.close()
Ответ 2
Для тех, кто ищет, как указать имя_службы вместо SID.
Из журнала изменений для SQLAlchemy 1.0.0b1 (выпущен 13 марта 2015 г.):
[oracle] [feature] Добавлена поддержка соединений cx_oracle с определенным именем службы, в отличие от имени tns, путем передачи ?service_name=<name>
в URL. Вытяните запрос любезно Sławomir Ehlert.
Это изменение вводит новый специфичный для Oracle диалект service_name
который может использоваться для построения строки подключения следующим образом:
from sqlalchemy import create_engine
from sqlalchemy.engine import url
connect_url = url.URL(
'oracle+cx_oracle',
username='some_username',
password='some_password',
host='some_host',
port='some_port',
query=dict(service_name='some_oracle_service_name'))
engine = create_engine(connect_url)
Ответ 3
Он все еще может не работать. Вам нужно взять вывод dsnStr и изменить строку, заменив SID на SERVICE_NAME и использовать эту переменную в строке con. Эта процедура работала для меня.
Ответ 4
Если вы используете sqlalchemy и ORACLE 12, похоже, что работает.
from sqlalchemy import create_engine
con='oracle://user:[email protected]:1521/?service_name=DDDD'
engine = create_engine(con)
Обратите внимание: вы должны использовать имя службы, а не идентификатор SID. Я не знаю почему, но простая строка соединения, использующая SID, не работает.
Ответ 5
SID может быть недоступен или вы не можете создать его для своей базы данных.
В моем случае я работаю с клиентской стороны, запрашивая доступ к базе данных облака, поэтому создание SID действительно не имеет смысла.
Вместо этого у вас может быть строка, которая выглядит примерно так:
"(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = something.cloud.company)
(PORT = 12345)) (ADDRESS = (PROTOCOL = TCP)(HOST = something.cloud.company)
(PORT = 12345)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME =
something.company)))"
Вы можете использовать его вместо SID.
connection = cx_Oracle.connect("username", "pw", "(DESCRIPTION = (ADDRESS =
(PROTOCOL = TCP)(HOST = something.cloud.company)(PORT = 12345)) (ADDRESS =
(PROTOCOL = TCP)(HOST = something.cloud.company)(PORT = 12345))
(CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = something.company)))")
Ответ 6
Я также встретился с этой проблемой. Решение:
1: get the service name at tnsnames.ora
2: put the service name in
con_str = "myuser/[email protected]:1521/ora1"