CX Oracle не подключается при использовании SID вместо имени службы в строке подключения
у меня есть строка подключения, которая выглядит так
con_str = "myuser/mypass@oracle.sub.example.com: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 с помощью SQLAlachemy
- Oracle SID и имя Службы; проблемы с подключением
- cx_Oracle & подключение к Oracle DB удаленно
Как правильно подключиться к Oracle, используя cx_Oracle
, С помощью SID
и не имя службы? Как это сделать без необходимости корректировать ? Мое приложение распространяется среди многих пользователей внутри и вносит изменения в TNSNAMES
файл менее идеален при работе с пользователями без прав администратора на своих машинах Windows. Кроме того, когда я использую имя службы, мне не нужно прикасаться к этому файлу вообще и хотелось бы сохранить его таким образом.
6 ответов
Я аналогичный сценарий, я смог подключиться к базе данных с помощью 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()
для тех, кто ищет как указать имя_службы вместо SID.
С изменений для SQLAlchemy 1.0.0b1 (выпущен 13 марта 2015 года):
[oracle] [feature] добавлена поддержка соединений cx_oracle с a конкретное имя службы, в отличие от имени tns, путем передачи
?service_name=<name>
к URL. Тянуть запрос любезно Sławomir Элерт.
изменение вводит новую, специфическую опцию диалекта 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)
Это все еще может не работать. Вам нужно взять вывод dsnStr и изменить строку, заменив SID на SERVICE_NAME и использовать эту переменную в строке con. Эта процедура сработала для меня.
Если вы используете sqlalchemy и ORACLE 12, кажется, работает следующее.
from sqlalchemy import create_engine
con='oracle://user:password@hostname:1521/?service_name=DDDD'
engine = create_engine(con)
Примечание, Вы должны использовать имя службы, а не SID. Я не знаю почему, но простая строка соединения, которая использует SID, не работает.
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)))")
Я тоже встретил эту проблему. Решение таково:
1: get the service name at tnsnames.ora
2: put the service name in
con_str = "myuser/mypass@oracle.sub.example.com:1521/ora1"