web-dev-qa-db-ja.com

接続文字列でサービス名の代わりにSIDを使用すると、cx_Oracleは接続しません

このような接続文字列があります

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で動作しますが、サービス名では動作しません)

cx_Oracleを使用し、サービス名ではなくSIDを使用してOracleに接続する適切な方法は何ですか? TNSNAMES.ORAファイルを調整せずにこれを行うにはどうすればよいですか?私のアプリケーションは内部で多くのユーザーに配布されており、TNSNAMESファイルに変更を加えることは、Windowsマシンの管理者権限のないユーザーを扱う場合には理想的ではありません。さらに、サービス名を使用する場合、このファイルにまったく触れる必要はなく、そのままにしておく必要があります。

29
Andy

同様のシナリオで、 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()
_
47
Andreas Fester

SIDの代わりにservice_nameを指定する方法を探している人向け。

SQLAlchemy 1.0.0b1の changelog から(2015年3月13日にリリース):

[Oracle] [機能] ?service_name=<name>をURLに渡すことにより、tns名ではなく、特定のサービス名へのcx_Oracle接続のサポートを追加しました。プルリクエスト(SławomirEhlert提供).

この変更により、新しい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
Piotr Dobrogost

SqlalchemyとOracle 12を使用している場合、次のように動作するようです。

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

SIDではなく、サービス名を使用する必要があることに注意してください。理由はわかりませんが、SIDを使用する単純な接続文字列は機能しません。

1
Mr. Mundkowsky

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)))")
0
Daniel Holliday

それでも動作しない場合があります。 dsnStrの出力を取得し、SIDをSERVICE_NAMEに置き換えて文字列を変更し、con文字列でその変数を使用する必要があります。この手順はうまくいきました。

0
Srinivas Ganti