Help us understand the problem. What is going on with this article?

[cx_Oracle入門](第12回) DB例外処理

連載目次

連載:cx_Oracle入門 目次

検証環境

  • Oracle Cloud利用
  • Oracle Linux 7.7 (VM.Standard2.1)
  • Python 3.6
  • cx_Oracle 8.0
  • Oracle Database 19.5 (ATP, 1OCPU)
  • Oracle Instant Client 18.5

cx_Oracle.DatabaseError

cx_Oracle.DatabaseErrorという例外が基本的なcx_Oracle利用時に発生した問題に対する例外となります。cx_Oracle.DatabaseError自体は、Python標準のErrorのサブクラスであるcx_Oracle.Errorのサブクラスとなっています。他にも多くのcx_Oracleの例外がありますが、それらはこれらのいずれかの例外のサブクラスとして定義されています。基本、内容を問わずcx_Oracleの例外をまとめてハンドリングしたい場合は、cx_Oracle.DatabaseErrorを使用します。

sample12a.py
import cx_Oracle

USERID = "admin"
PASSWORD = "FooBar"
DESTINATION = "atp1_aaa"
SQL = """
        select object_id, owner, object_name, object_type
          from all_objects
         order by object_id
         fetch first 5 rows only
"""

with cx_Oracle.connect(USERID, PASSWORD, DESTINATION) as connection:
        cursor = connection.cursor()
        cursor.execute(SQL)
        for row in cursor:
                print(row)
        cursor.close()
$ python sample12a.py
Traceback (most recent call last):
  File "sample12a.py", line 13, in <module>
    with cx_Oracle.connect(USERID, PASSWORD, DESTINATION) as connection:
cx_Oracle.DatabaseError: ORA-12154: TNS:could not resolve the connect identifier specified

sample12a.pyでは、4行目のDESTINATION変数の内容に存在しないTNS接続子を指定しています。ですので実行すると必ず接続エラーになります。このサンプルのように、コーディング上、特段のエラーハンドリングを行っていない場合は、cx_Oracle.DatabaseErrorの例外が発生します。例外のメッセージ内容は、エラー内容に該当するOracle Databaseのエラー番号(ORA-xxxxx、実行例の「ORA-12154」)とエラー番号に対応したエラーメッセージ(実行例の「TNS:could not resolve the connect identifier specified」)です。このサンプル実行時に環境変数NLS_LANGを指定していないので、エラーメッセージは英語になっています。日本語のエラーメッセージを受け取りたい場合は、NLS_LANGを設定してください。

例外の一覧

cx_Oracle.Errorとcx_Oracle.DatabaseError以外にも、個別の事象に応じた例外や、DB APIで規定されている例外が定義されています。

例外名 説明
cx_Oracle.InterfaceError cx_Oracleのインターフェースを利用している際の問題に関する例外です。一例としてはcx_OralceのAPIの利用方法を誤っている場合などに発生します。
cx_Oracle.DataError 0除算や桁あふれなど、データ内容に問題がある場合に発生します。
cx_Oracle.OperationalError ORA-600のようなDB内部のエラーや、ORA-3135のような通信エラーなどの場合に発生します。
cx_Oracle.IntegrityError 参照整合性制約違反のようなデータの整合性に関する問題がある場合に発生します。
cx_Oracle.InternalError 内部エラーの際に発生します。ORA-600など事前に定義されている内部エラーはcx_Oracle.OperationalErrorになるので、これらのエラーコードにならない内部の問題が該当します。一例としては無効になったカーソルにアクセスした場合などに発生します。
cx_Oracle.ProgrammingError プログラミング上の問題に関する例外です。一例としては、発行するSQL文に問題がある場合などに発生します。
cx_Oracle.NotSupportedError 存在しないcx_Oralceのメソッドをコールしたような場合に発生します。
cx_Oracle.Warning DB APIに存在するため定義はされていますが、cx_Oracleでは実質的に利用されません。

例外処理で扱える変数

例外処理の中では、以下のような読み取り専用の変数の情報を参照することが可能です。これらはまとめてargsタプルに含まれます。

変数名 説明
_Error.code Oracle Databaseのエラー番号
_Error.offset エラーのオフセット
_Error.message エラーメッセージ
_Error.context エラーのコンテキスト情報
_Error.isrecoverable 回復可能なエラーであるか否かのbool型。本変数を利用するためには、Oracle Server / Client共に12.1以降である必要がある。バージョン条件を満たさない場合は常にFalseが格納される

一例としては、以下の様に例外部で上記変数を使用します。このサンプルでは、PL/SQLのユーザー定義例外機能を利用して、故意にみなさん大好き(???)なORA-600を発生させています。

sample12b.py
import cx_Oracle

USERID = "admin"
PASSWORD = "FooBar"
DESTINATION = "atp1_low"
SQL = """
declare
  e600 exception;
  pragma exception_init(e600, -600);
begin
  raise e600;
end;
"""
try:
    connection = cx_Oracle.connect(USERID, PASSWORD, DESTINATION)
    cursor = connection.cursor()
    cursor.execute(SQL)
except cx_Oracle.OperationalError as ex:
    error, = ex.args
    print("エラーが発生しました。エラーコードとメッセージを管理者に連絡してください。")
    print("エラーコード : ", error.code)
    print("エラーメッセージ : ", error.message)
finally:
    cursor.close()
    connection.close()
$ python sample12b.py
エラーが発生しました。エラーコードとメッセージを管理者に連絡してください。
エラーコード :  600
エラーメッセージ :  ORA-00600: 内部エラー・コード, 引数: [600], [], [], [], [], [], [], [], [], [], [], []
ORA-06512: 行6
nakaie
日本オラクル所属のOracle Database中心のエンジニアです。 投稿内容は個人の見解であり所属する組織の公式見解ではありません。 Twitter : @HNakaie
oracle
Oracle Cloudは、最先端の機能をSoftware as a Service、Platform as a ServiceおよびInfrastructure as a ServiceおよびData as a Serviceとして提供します。
https://cloud.oracle.com/ja_JP/home
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした