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, используя 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"