web-dev-qa-db-fra.com

cx_Oracle ne se connecte pas lorsque SID est utilisé à la place du nom du service dans la chaîne de connexion

J'ai une chaîne de connexion qui ressemble à ceci

con_str = "myuser/[email protected]:1521/ora1"

ora1 est le SID de ma base de données. L'utilisation de ces informations dans SQL Developer fonctionne correctement, ce qui signifie que je peux me connecter et interroger sans problèmes.

Cependant, si je tente de me connecter à Oracle à l'aide de cette chaîne, elle échoue.

cx_Oracle.connect(con_str)

DatabaseError:  ORA-12514:  TNS:listener  does  not  currently  know  of  service  requested  in  connect  descriptor

Ce format de chaîne de connexion fonctionne si le ora1 est un nom de service. 

J'ai vu d'autres questions qui semblent avoir l'inverse de mon problème (cela fonctionne avec SID, mais pas le nom du service)

Quelle est la bonne façon de se connecter à Oracle, en utilisant cx_Oracle, en utilisant une SID et non un nom de service? Comment faire cela sans avoir à ajuster le fichier TNSNAMES.ORA? Mon application est distribuée à de nombreux utilisateurs en interne et apporter des modifications au fichier TNSNAMES n'est pas idéal lorsque vous traitez avec des utilisateurs sans privilèges d'administrateur sur leurs ordinateurs Windows. De plus, lorsque j'utilise le nom du service, je n'ai pas du tout besoin de toucher ce fichier et j'aimerais qu'il le conserve ainsi. 

26
Andy

Dans un scénario similaire, je pouvais me connecter à la base de données en utilisant cx_Oracle.makedsn() pour créer une chaîne dsn avec un SID (au lieu du nom du service):

dsnStr = cx_Oracle.makedsn("Oracle.sub.example.com", "1521", "ora1")

Cela retourne quelque chose comme 

(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(Host=Oracle.sub.example.com)(PORT=1521)))(CONNECT_DATA=(SID=ora1)))

qui peut ensuite être utilisé avec cx_Oracle.connect() pour se connecter à la base de données:

con = cx_Oracle.connect(user="myuser", password="mypass", dsn=dsnStr)
print con.version
con.close()
41
Andreas Fester

Pour ceux qui recherchent comment spécifier nom_service au lieu de SID.

De changelog pour SQLAlchemy 1.0.0b1 (publié le 13 mars 2015):

[Oracle] [fonctionnalité] Ajout du support pour les connexions cx_Oracle à un fichier nom de service spécifique, par opposition à un nom de tns, en passant ?service_name=<name> à l'URL. Tirer demande de courtoisie Sławomir Ehlert.

La modification introduit une nouvelle option service_name spécifique au dialecte Oracle, qui peut être utilisée pour créer une chaîne de connexion comme celle-ci:

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
Piotr Dobrogost

Les SID peuvent ne pas être facilement accessibles ou ne pas l'avoir créé pour votre base de données. 

Dans mon cas, je travaille du côté client pour demander l’accès à une base de données en nuage, ce qui n’a pas vraiment de sens. 

Au lieu de cela, vous pourriez avoir une chaîne qui ressemble à ceci: 

"(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)))"

Vous pouvez l'utiliser en remplacement du 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)))")
0
Daniel Holliday

Cela ne fonctionne toujours pas. Vous devez extraire la sortie de dsnStr et modifier la chaîne en remplaçant SID par SERVICE_NAME et utiliser cette variable dans la chaîne con. Cette procédure a fonctionné pour moi.

0
Srinivas Ganti

Si vous utilisez sqlalchemy et Oracle 12, voici ce qui semble fonctionner. 

from sqlalchemy import create_engine
con='Oracle://user:password@hostname:1521/?service_name=DDDD'
engine = create_engine(con)

Notez que vous devez utiliser le nom du service et non le SID. Je ne sais pas pourquoi, mais la simple chaîne de connexion qui utilise SID ne fonctionne pas.

0
Mr. Mundkowsky