ORA-12154「TNS: 指定された接続識別子を解決できませんでした」の原因と対処法|tnsnames.ora が正しいのに出るケースも実機で再現

新しい接続先を tnsnames.ora に追加した直後や、クライアント環境を移行した後に、sqlplus からの接続が ORA-12154 で失敗する。
tnsnames.ora を開いて何度見直しても、エントリは正しく書けているように見える…。

ORA-12154 は「接続文字列に書いた接続識別子を、クライアントが解決できなかった」ことを示すエラーです。
今回は、ORA-12154 になる原因5パターンを実機で再現します。
あわせて、ORA-12154 になりそうで別のエラーになる紛らわしいケース(ORA-12504・ORA-12545)と、tnsping を使った切り分け手順も実機ログとともに整理します。


1. 症状

tnsnames.ora のエントリ名を指定した TNS 接続を試みると、待たされることなく即座に ORA-12154 が返ります。

$ sqlplus system/oracle@V11C19U

ERROR:
ORA-12154: TNS: 指定された接続識別子を解決できませんでした

このとき、DB サーバ側のリスナーとデータベースは正常に稼働しています。
ORA-12154 は接続識別子(@ の後ろに書いた文字列)をクライアント内で解決する処理の失敗で、失敗した時点で接続要求はネットワークに出ていません。
そのため、サーバ側をいくら調べても原因は見つからず、調査はクライアント側の設定に絞られます。


2. 原因の仕組み

Oracle への TNS 接続は、次の4段階で進みます。
ORA-12154 は、このうち①「接続先の情報を解決する」段階の失敗です。

① 接続先の情報を解決する(クライアント内)
      │ エントリ名を tnsnames.ora 等で引けない → ORA-12154 ★本記事
      │ エントリ内ホスト名の名前解決に失敗 → ORA-12545 ★本記事(後半の章で解説)
      ▼
② 接続先ホストに到達する(ネットワーク)
      │ 到達できない → ORA-12543(即時)/ ORA-12170(応答がなくタイムアウト)
      ▼
③ リスナーに接続する(ポート 1521)
      │ 接続を拒否される → ORA-12541
      ▼
④ リスナーがサービスへ転送する
      │ サービス名が未登録 → ORA-12514
      ▼
   接続成功

接続識別子とは、接続文字列の @ の後ろに書く文字列のことです。
@V11C19U のようなエントリ名でも、@ホスト:ポート/サービス名 の直接指定(簡易接続ネーミング。EZConnect とも呼ばれます)でも、クライアントはまずこの文字列を「どのホストの・どのポートの・どのサービスに接続するか」という具体的な接続先情報に変換します。
この変換(解決)に使われるのが tnsnames.ora で、どの方式で解決を試みるかは sqlnet.ora の NAMES.DIRECTORY_PATH で決まります(本検証環境では TNSNAMES, ONAMES, HOSTNAME の順)。
tnsnames.ora と sqlnet.ora は、どちらもデフォルトでは $ORACLE_HOME/network/admin に置かれ、環境変数 TNS_ADMIN でこの置き場所を変更できます(TNS_ADMIN は原因パターン3(TNS_ADMIN の向き先)で再現します)。
Instant Client を使っている場合は、instantclient_リリース番号/network/admin 配下がデフォルトの置き場所です。
NAMES.DIRECTORY_PATH に並ぶ値は、それぞれ解決方式を表します。

解決方式
TNSNAMEStnsnames.ora で解決する
HOSTNAME直接指定(簡易接続ネーミング)を有効にする
ONAMES旧方式(Oracle Names)の値(19c の『Database Net Servicesリファレンス』には記載なし)

なお、『Database Net Servicesリファレンス』では、EZCONNECT と HOSTNAME は同じ簡易接続ネーミング・メソッドを指す値とされています。
どの方式でも解決できなかったときに返るのが ORA-12154 です。

②以降のエラー(ORA-12543ORA-12541ORA-12514)は「解決した接続先に接続しに行った結果」の失敗であるのに対し、ORA-12154 は接続しに行く前の失敗です。
つまり、ORA-12154 が出ている時点で、ネットワークやリスナーを調べる以前に、接続先がどこなのかをクライアントが特定できていません。


3. ORA-12154 の原因パターン一覧

原因は次の5パターンに整理できます。
いずれも実機(Oracle Database 19c(19.28 RU)・Oracle Linux 8.9)で再現して確認したものです。

#原因パターン起きやすい場面
1エントリ名が tnsnames.ora に定義されていないエントリ名の書き間違い・必要なエントリの追加漏れ
2直接指定のホスト名が解決できないホスト名の書き間違い・DNS / hosts への登録漏れ
3TNS_ADMIN が別の tnsnames.ora を向いている検証用に設定した TNS_ADMIN の残存・環境変数の設定ミス
4エントリ名の行頭にスペースが入っているtnsnames.ora の手編集・エントリのコピー&ペースト
5sqlnet.ora の NAMES.DEFAULT_DOMAIN がドメインを付加している別環境の sqlnet.ora を流用した・ドメイン運用環境からの移行

パターン1・2は接続文字列側、パターン3〜5は設定ファイル側の原因です。
パターン3〜5に共通するのは、「tnsnames.ora のエントリ自体は正しいのに ORA-12154 になる」ことです。
エントリを何度見直しても原因が見つからない場合は、tnsnames.ora 以外(環境変数・sqlnet.ora・行頭の見えない文字)を確認します。

パターン1: エントリ名が tnsnames.ora に定義されていない

最も分かりやすいパターンです。
接続文字列に書いたエントリ名が tnsnames.ora に存在しないと、ORA-12154 になります。

$ sqlplus system/oracle@NOSUCHENTRY

ERROR:
ORA-12154: TNS: 指定された接続識別子を解決できませんでした

エントリ名の書き間違いのほか、「アプリの接続設定には書いてあるが、そのクライアントの tnsnames.ora にはまだエントリを追加していない」という追加漏れの形でも起きます。
tnsnames.ora に該当のエントリ名があるかを確認します。

パターン2: 直接指定のホスト名が解決できない

@ホスト:ポート/サービス名 の直接指定で、ホスト名の名前解決に失敗するケースです。

$ sqlplus system/oracle@nosuchhost:1521/v11c19u

ERROR:
ORA-12154: TNS: 指定された接続識別子を解決できませんでした

エラー番号に注意が必要です。
ホスト名の解決失敗というと ORA-12545(ターゲット・ホストが存在しない)を連想しますが、実機(19c)で確認すると、直接指定のホスト名が解決できない場合は ORA-12154 になりました。
ホスト名が解決できないと、接続文字列全体が「解決できない接続識別子」として扱われるためです。
ORA-12545 になるのは、tnsnames.ora のエントリ経由で、エントリ内の HOST が解決できない場合です(後述の「ORA-12545 になるケース」の章で再現します)。

ホスト名が DNS または hosts ファイルで解決できるかは、getent hosts <ホスト名> で確認できます。

パターン3: TNS_ADMIN が別の tnsnames.ora を向いている

環境変数 TNS_ADMIN は、tnsnames.ora や sqlnet.ora を探すディレクトリを指定します。
この向き先が誤っていると、正しい tnsnames.ora が読まれず、ファイル自体は正しいのに ORA-12154 になります。

ただし、実機で確認すると、「TNS_ADMIN の向き先が誤っている=即 ORA-12154」ではありませんでした。
挙動を3つの状態で比較したのが次の表です(本検証環境(19c・Linux)での実測です)。

TNS_ADMIN の状態接続結果(実測)
未設定$ORACLE_HOME/network/admin の tnsnames.ora で解決・接続成功
設定あり・向き先に tnsnames.ora が無い$ORACLE_HOME/network/admin へフォールバックして接続成功
設定あり・向き先に別の tnsnames.ora が有る(エントリなし)そのファイルだけが使われ ORA-12154

フォールバックが起きる理由は、tnsnames.ora の探索順序にあります。
『Database Net Servicesリファレンス』では、tnsnames.ora は「最初に TNS_ADMIN で指定されたディレクトリを探し、そこに無ければ $ORACLE_HOME/network/admin を探す」と定められています。

この探索順序を踏まえると、先ほどの表の挙動はこう説明できます。

  • TNS_ADMIN の向き先に tnsnames.ora が無い場合: 探索が $ORACLE_HOME/network/admin へ進み、そちらの tnsnames.ora が読まれます。そのファイルに目的のエントリがあれば(本検証環境がこの状態です)、接続は成功します
  • TNS_ADMIN の向き先に tnsnames.ora が有る場合: 探索はそこで止まり、向き先のファイルだけが読まれます(実測では、目的のエントリを含む $ORACLE_HOME/network/admin 側の tnsnames.ora は読まれませんでした)。向き先のファイルに目的のエントリが無ければ、ORA-12154 になります

つまり、ORA-12154 になるのは、向き先に別の tnsnames.ora が存在して、そこに目的のエントリが無い場合です。
検証用の設定ファイル一式を置いたディレクトリを TNS_ADMIN が指したまま、という形で起きます。

実機での再現です。
目的のエントリ(V11C19U)を含まない tnsnames.ora を置いたディレクトリへ TNS_ADMIN を向けると、ORA-12154 になります。

$ export TNS_ADMIN=/tmp/empty_tns          # V11C19U エントリの無い tnsnames.ora を置いたディレクトリ
$ sqlplus system/oracle@V11C19U

ERROR:
ORA-12154: TNS: 指定された接続識別子を解決できませんでした

この状態でも、tnsnames.ora を使わない直接指定なら接続できます。

$ sqlplus system/oracle@localhost:1521/v11c19u

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.28.0.0.0
に接続されました。

「エントリ名では ORA-12154 になるが、直接指定なら接続できる」なら、DB・リスナー・ネットワークは正常で、エントリ名の解決だけが失敗していると確定できます。
この対比は切り分けにそのまま使えます(後述の「切り分け手順」の章)。

TNS_ADMIN が原因だった場合は、環境変数を修正(一時的な確認なら unset TNS_ADMIN)すれば、それだけで復旧します。
現在の設定値は env | grep TNS で確認できます。

パターン4: エントリ名の行頭にスペースが入っている

tnsnames.ora の古典的な原因です。
tnsnames.ora では、エントリ名は行頭(1桁目)から始まる必要があります。
行頭にスペースがあると、その行は前のエントリの続き(継続行)として扱われ、エントリ名として認識されません。

実機で、V11C19U エントリの行頭にスペースを1つ入れて再現しました。
変更前後の差分は次の1行だけです(< が変更後・> が変更前です)。

$ diff tnsnames.ora tnsnames.ora.20260810
34c34
<  V11C19U =
---
> V11C19U =

この状態で接続すると、ORA-12154 になります。

$ sqlplus system/oracle@V11C19U

ERROR:
ORA-12154: TNS: 指定された接続識別子を解決できませんでした

スペース1文字なので、ファイルを目視しても気づくのは困難です。
行頭にスペースの入った行は、次のコマンドで機械的に見つけられます。

$ grep -n '^ ' tnsnames.ora

該当行があれば、行番号付きで表示されます。
cat -A tnsnames.ora(スペース・タブ・行末を可視化して表示)でも確認できます。

パターン5: sqlnet.ora の NAMES.DEFAULT_DOMAIN がドメインを付加している

tnsnames.ora には一切触れていないのに ORA-12154 になるパターンです。
sqlnet.ora に NAMES.DEFAULT_DOMAIN が設定されていると、ドメインの付いていないエントリ名にそのドメインが自動的に付加されてから解決されます。

実機で、sqlnet.ora に次の1行を追記して再現しました。

$ echo 'NAMES.DEFAULT_DOMAIN = example.com' >> sqlnet.ora
$ sqlplus system/oracle@V11C19U

ERROR:
ORA-12154: TNS: 指定された接続識別子を解決できませんでした

接続文字列は @V11C19U のままですが、DEFAULT_DOMAIN により V11C19U.example.com という名前で tnsnames.ora が検索されます。
tnsnames.ora のエントリ名は V11C19U のままなので一致せず、ORA-12154 になります。

「tnsnames.ora を何度見直しても正しいのに ORA-12154 が出る」ときは、sqlnet.ora に NAMES.DEFAULT_DOMAIN が入っていないかを確認します。
別環境から sqlnet.ora ごと設定ファイルをコピーしてきた場合などに、意図しない DEFAULT_DOMAIN が紛れ込みます。


4. ORA-12154 にならないケース: tnsnames.ora の構文エラー

tnsnames.ora の構文エラー(括弧の対応漏れなど)も ORA-12154 の原因としてよく挙げられます。
ところが、実機で再現すると、記述誤りの場所によっては別のエラー番号になりました。

ORCL19U エントリの (SERVER = DEDICATED) の閉じ括弧を1つ削除して再現します。
変更は次の1行だけです。

$ diff tnsnames.ora tnsnames.ora.20260810
12c12
<       (SERVER = DEDICATED
---
>       (SERVER = DEDICATED)

閉じ括弧を削除したエントリ自身に接続すると、返ってきたのは ORA-12154 ではなく ORA-12504 でした。

$ sqlplus system/oracle@ORCL19U

ERROR:
ORA-12504: TNS: リスナーはCONNECT_DATAのSERVICE_NAMEを取得できませんでした。

閉じ括弧が欠けたことで、次の行の (SERVICE_NAME = orcl19u) が SERVER の値の一部として解釈され、SERVICE_NAME の無い接続要求が組み立てられました。
エントリの ADDRESS 部(HOST・PORT)は無傷のため、接続要求はリスナーまで届き、リスナー側で「SERVICE_NAME が取得できない」というエラーになった、という流れです。
「構文エラー=即 ORA-12154」ではなく、どの部分に誤りがあるかでエラー番号が変わります。
ORA-12154 になるのは、エントリ名そのものが見つからない・読めない場合です。

もう1点、記述誤りのあるエントリの影響範囲も実測しました。
同じファイルの、記述誤りのある ORCL19U エントリより後ろに定義されている V11C19U エントリへ接続すると、こちらは正常に接続できました。

$ sqlplus system/oracle@V11C19U

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.28.0.0.0
に接続されました。

少なくとも今回の記述誤り(エントリ内の閉じ括弧1つ不足)では、他のエントリの解決には波及しませんでした。
「自分のエントリは正しいのに、他のエントリの構文エラーの影響で失敗しているのではないか」と tnsnames.ora 全体を精査する前に、まず自分のエントリ名が解決できているか(後述の tnsping)を確認します。


5. ORA-12545 になるケース: エントリ内の HOST が解決できない

パターン2(直接指定のホスト名解決失敗)と対になるケースです。
tnsnames.ora のエントリは存在するが、エントリ内の HOST に書かれたホスト名が解決できない場合は、ORA-12154 ではなく ORA-12545 になります。

HOST に解決できないホスト名を書いたエントリ(BADHOST)を tnsnames.ora に追加して再現しました。

BADHOST =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = nosuchhost)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = v11c19u)
    )
  )
$ sqlplus system/oracle@BADHOST

ERROR:
ORA-12545:
ターゲット・ホストまたはオブジェクトが存在しないため、接続に失敗しました

同じ「ホスト名を解決できない」という失敗でも、接続文字列の書き方でエラー番号が分かれます。

接続文字列の書き方失敗した解決エラー(実測)
直接指定(@nosuchhost:1521/サービス名接続識別子そのものの解決ORA-12154
エントリ名経由(@BADHOST・HOST が解決不能)エントリ解決は成功・その中の HOST の解決ORA-12545

ORA-12545 が出た場合、エントリ名の解決は成功しています。
確認すべきは tnsnames.ora のエントリの有無ではなく、エントリ内の HOST に書かれたホスト名と、DNS / hosts ファイルの登録内容です。
サーバ移行やホスト名変更の後、エントリ内の HOST が旧ホスト名のまま、という形で起きます。


6. 切り分け手順: tnsping で「どう解決されたか」を確認する

ORA-12154 の切り分けには tnsping が使えます。
tnsping は、エントリ名の解決とリスナーへの到達確認だけを行うツールです。
sqlplus と違って DB へのログイン自体を行わないため、ユーザー名・パスワードの指定がそもそもなく、DB アカウントを知らなくても実行できます。
出力には、切り分けに使える情報が3つ含まれます。

正常なエントリに対する実行例です。

$ tnsping V11C19U

TNS Ping Utility for Linux: Version 19.0.0.0.0 - Production on 10-8月 -2026 13:31:06

Copyright (c) 1997, 2025, Oracle.  All rights reserved.

パラメータ・ファイルを使用しました:
/u01/app/oracle/product/19.0.0/dbhome_1/network/admin/sqlnet.ora


エイリアスを解決するためにTNSNAMESアダプタを使用しました。
(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = db-node)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = v11c19u)))に接続の試行中
OK (0ミリ秒)

読み取れる情報は次の3つです。

  1. パラメータ・ファイルのパス: 実際に読み込まれた sqlnet.ora の場所が表示されます。想定と異なるディレクトリのパスが表示されていないかを確認します
  2. 使われた解決方式: この例では「TNSNAMESアダプタ」= tnsnames.ora で解決されたことが分かります
  3. 解決後の接続記述子: エントリがどう解決されたか(HOST・PORT・SERVICE_NAME)の全文が表示されます。意図した接続先になっているかを目視できます

ただし、エラー番号には注意が必要です。
sqlplus で ORA-12154 になるケースを tnsping で実行すると、番号が TNS-03505 に変わります。

$ tnsping NOSUCHENTRY

TNS Ping Utility for Linux: Version 19.0.0.0.0 - Production on 10-8月 -2026 13:29:16

Copyright (c) 1997, 2025, Oracle.  All rights reserved.

パラメータ・ファイルを使用しました:
/u01/app/oracle/product/19.0.0/dbhome_1/network/admin/sqlnet.ora

TNS-03505: 名前の解決に失敗しました。

sqlplus と tnsping のエラー番号の対応は、実測では次のとおりでした。

失敗の内容sqlplus(実測)tnsping(実測)
未定義のエントリ名ORA-12154TNS-03505
直接指定のホスト名解決失敗ORA-12154TNS-03505
エントリ内の HOST 解決失敗ORA-12545TNS-12545
正常接続成功OK (Nミリ秒)

エントリ名の解決に失敗するケース(ORA-12154 相当)だけ、tnsping では TNS-03505 に番号が変わります。
「ORA-12154」で調べていて tnsping の出力に 12154 が見当たらなくても、TNS-03505 が同じ失敗を指しています。

もう1つの切り分けが、パターン3(TNS_ADMIN の向き先)の再現でも使った直接指定との対比です。

$ sqlplus system/oracle@localhost:1521/v11c19u

直接指定はエントリ名の解決を使わないため、tnsnames.ora・TNS_ADMIN・DEFAULT_DOMAIN の影響を受けません(ホスト名解決は OS 任せのため、IP アドレスか解決できるホスト名で指定します)。
エントリ名では ORA-12154、直接指定では接続成功なら、DB もリスナーも正常で、エントリ名の解決だけが失敗していると絞り込めます。


7. Q&A

Q: tnsnames.ora のエントリは正しく書けているのに ORA-12154 になります。どこを確認すればよいですか?

A: tnsnames.ora 以外の3か所を確認します。
①環境変数 TNS_ADMIN が別のディレクトリを向いていないか(env | grep TNS・向き先に別の tnsnames.ora があるとそちらだけが読まれます)。
②sqlnet.ora に NAMES.DEFAULT_DOMAIN が設定されていないか(エントリ名にドメインが付加されて検索されるため一致しなくなります)。
③エントリ名の行頭にスペースが入っていないか(grep -n '^ ' tnsnames.ora で機械的に見つけられます)。
いずれも「エントリの記述内容は正しいのに ORA-12154 になる」原因として実機で再現したものです。

Q: tnsping でも ORA-12154 を確認できますか?

A: 確認できますが、エラー番号が変わります。
sqlplus で ORA-12154 になるケースは、tnsping では TNS-03505(名前の解決に失敗しました)になります(本文の対応表を参照)。
番号は変わりますが、tnsping は読み込まれた sqlnet.ora のパスと解決後の接続記述子を表示するため、切り分けの初動としては sqlplus で再試行するより多くの情報が得られます。

Q: ORA-12154 と ORA-12545 は何が違いますか?

A: どの名前の解決に失敗したかが異なります。

エラー失敗した解決最初に確認する場所
ORA-12154接続識別子(エントリ名・接続文字列全体)の解決tnsnames.ora のエントリ有無・TNS_ADMIN・sqlnet.ora
ORA-12545エントリ内に書かれた HOST(ホスト名)の解決エントリの HOST・DNS / hosts ファイル

同じ「ホスト名が解決できない」でも、直接指定なら ORA-12154、tnsnames.ora エントリ経由なら ORA-12545 と、接続文字列の書き方で番号が分かれる点に注意してください。

Q: DB サーバ側で調べることはありますか?

A: ORA-12154 の原因調査は、接続に失敗したクライアント側で行います。
接続識別子の解決はクライアント内の処理で、失敗した時点で接続要求は送信されないためです。
DB サーバに接続できる別のクライアントがあるなら、そのマシンの tnsnames.ora・sqlnet.ora と比較すると、差分から原因を絞り込めます。

Q: 接続文字列を修正できないアプリケーションでも切り分けはできますか?

A: できます。
本文の tnsping と直接指定の対比は、アプリケーションと同じクライアント環境の OS 上で実行する切り分けで、アプリケーション側の変更は不要です。
同じ接続識別子で tnsping が TNS-03505 になれば、アプリケーションの設定ではなく、そのクライアント環境の名前解決(tnsnames.ora・TNS_ADMIN・sqlnet.ora)の問題と確定できます。
ただし、この切り分けが成り立つのは、アプリケーションが tnsnames.ora を参照して接続している場合です。
JDBC Thin ドライバのように、デフォルトでは tnsnames.ora を読まない接続方式では、アプリケーションのエラーと tnsping の結果が対応しないことがあります。


8. まとめ

ORA-12154 は「接続識別子をクライアント内で解決できなかった」エラーです。
接続要求がネットワークに出る前の失敗のため、リスナーやネットワークの調査より先に、クライアント側の接続文字列と設定ファイル(tnsnames.ora・sqlnet.ora・TNS_ADMIN)を確認します。
tnsnames.ora のエントリが正しくても、TNS_ADMIN の向き先・NAMES.DEFAULT_DOMAIN・行頭スペースで発生する点に注意してください。

ORA-12154 切り分けフロー

TNS接続で ORA-12154
        │
        ▼
接続文字列はどちらの形式か
        │
        ├─ 直接指定(@ホスト:ポート/サービス名)
        │    → ホスト名の名前解決を確認
        │      getent hosts <ホスト名>
        │      解決できなければ綴りの修正・DNS / hosts への登録
        │
        └─ エントリ名(@V11C19U など)
                │
                ▼
        tnsping <エントリ名> を実行
                │
                ├─ OK
                │    → エントリ名の解決は成功している
                │      (エラーが sqlplus 側だけなら、実行ユーザー・
                │        実行環境ごとの環境変数の差を確認)
                │
                └─ TNS-03505(名前の解決に失敗)
                        │
                        │ 出力冒頭の「パラメータ・ファイル」のパスが
                        │ 想定のディレクトリかを先に確認
                        ▼
                ① tnsnames.ora に該当エントリ名があるか
                ② TNS_ADMIN の向き先(env | grep TNS)
                ③ エントリ名の行頭スペース(grep -n '^ ' tnsnames.ora)
                ④ sqlnet.ora の NAMES.DEFAULT_DOMAIN の有無