J'ai une chaîne de connexion qui ressemble à ceci
con_str = "myuser/[email protected]:1521/ora1"
Où 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.
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()
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)
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)))")
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.
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.