cx_Oracle

 cx_Oracle はOracleデータベースを操作する機能を提供するPythonの拡張モジュールです。 www.python.orgが提唱する Python DATABASE API 2.0 にも準拠しており、 幾つかあるPythonのOracleモジュールの中でも特に完成度が高いソフトウェアです。 しかもこのよーなソフトがオープンソースで開発・配布されているというのですから、 もはや喜んでいいやらありがたがっていいやら、困ってしまいます。 古来よりわが国では、このような状況こそを指してマイッチング(maitching) と呼んできたのです。(素で流して下さい) 当サイトでは、次の環境で日本語の扱いも含めて動作確認ができたので、 この環境での使い方をご紹介します。

インストール
 cx_Oracleは冒頭の配布サイトから無償で入手できます。Windowsクライアントに対しては、 Python 2.0用、Python 2.1用のコンパイル済みバイナリ(.pyd) が配布されています。UNIX環境ではソース配布からのコンパイルが必要になります。
 Windows用バイナリのインストールはとても簡単で、 アーカイブを展開してできる cx_Oracle.pyd をPythonのシステムパス(sys.path) に含まれるディレクトリのどこかにコピーすれば完了です。 何のことか分からない、という場合は C:\Program Files\Python\Dlls というディレクトリに置けばOKです。

SELECT文による問合せ
 では、簡単なサンプルで動作をご紹介とまいりましょう。 cx_Oracleでおらおらする処理の流れは、大きくは次のようになります:

  1. connect関数でOracleインスタンスに接続(ログオン)します。
  2. cursorメソッドで接続に対して「カーソル」を作成します。
  3. SQL文を実行します。
  4. 問合せの場合は、結果を取得します。
  5. カーソルを閉じます。
  6. 接続を終了(ログオフ)します。
まずは、SELECT文で問合せを行って、結果を表示してみます。

# モジュールのインポート。
import cx_Oracle
# インスタンスに接続します。Oracleの場合、引数には
# 「ユーザ/パスワード@ホスト文字列」
# つまりSQL*PlusやSQL*Loaderで指定するパラメータと同じものを渡せばOKです。
con = cx_Oracle.connect("urano/urano398@oraora4")

# SQL文を実行するには、接続に対して「カーソル」を作成します。
ora = con.cursor()

# SQL文の実行はexecuteメソッドで行います。
s = "SELECT * FROM QUOTATION"
ora.execute(s)

# 結果はfetchoneメソッドで1行ずつ取得でき、
# 戻り値は各カラムの値からなるたっぷるです。
# Noneが返ったら処理終了です。
row = ora.fetchone()
while row != None:
    print str(row[0]) + ":" + str(row[1])
    row = ora.fetchone()

# カーソルを閉じます。
ora.close()
# 接続を終了します。
con.close()
# end.

 ご紹介、といってもソースプログラム中にコメントで書いた通りなのです。 一点だけ、日本語のデータを取得する場合ですが、特に気にする必要はありません。 環境変数NLS_LANGを正しくセットしておけば、 日本語のデータもOracleのエラーメッセージも化けずにそのまま返ってきます。 これは内部文字列がUTF-8になっているTclよりもPythonの単純な点です (それがいいのか、わるいのかは、おいといて)。

更新SQL文の発行
 UPDATE文、INSERT文、DELETE文でおらおらする場合も、手順はほとんど変わりません。 下のサンプルのように、とても簡単です。

import cx_Oracle
con = cx_Oracle.connect("urano/urano398@oraora4")
ora = con.cursor()
s = """
INSERT INTO QUOTATION(ORDER_NUMBER, VENDOR_CODE, PARTS_CODE, QUOTATION_DATE)
 VALUES('Q15678-982D124', 'V1056SX2', '0645182945', '01-07-20')
"""
ora.execute(s)
rows = ora.rowcount
print "行数=" + str(rows)
# トランザクションのコミットまたはロールバックは、接続オブジェクトの
# メソッドで下のように行います。
# con.commit()
# con.rollback()
ora.close()
con.close()
# end.

カーソルのrowcount()メソッドは、SQL*Plusで「○行が更新されました」 「○行が削除されました」というときに出るような行数を返すメソッドです。

バインド変数とストアドプロシージャのコール
 cx_Oracleでストアドプロシージャやストアドファンクションをコールするには、 カーソルのexecute()メソッドにSQL文の代わりにPL/SQL無名ブロックを渡せばOKです。 OKです…が、 プロシージャやファンクションの戻り値はどうやって取得すればいいの? というわけで、 バインド変数という便利な機能を使うことになります。
まずは簡単なストアドプロシージャを定義しておきます。 次の例は単に2つの引数の値を足し、3つめのOUT引数に格納して戻るというプロシージャです。

CREATE OR REPLACE PROCEDURE SAMPLE01(
  VAL1 IN NUMBER, VAL2 IN NUMBER, OVAL OUT NUMBER
) IS
BEGIN
  OVAL := VAL1 + VAL2;
END;
/

では、このプロシージャをcx_Oracleから呼び出しておらおらしてみます。

import cx_Oracle
con = cx_Oracle.connect("urano/urano398@oraora4")
ora = con.cursor()
oval = 0
s = """
begin
  sample01(10, :val2, :oval);
end;
"""
ora.execute(s, val2 = 20, oval = -1)
b = ora.fetchbinds()
print "取得しました:" + str(b['oval'])
ora.close()
con.close()

 カーソルのexecute()メソッドに渡す変数(aka.上の変数s)で、 前2例でSQL文を渡していたのと異なり、今度は無名PL/SQLブロックを渡しています。 無名PL/SQLブロックの中には、好きな識別子名の先頭にコロンをつけ、 バインド変数として識別子を潜ませることができます(上の:val2と:oval)。 これは、ブロックに対してIN変数でもOUT変数でも構いません。 で、execute()メソッドの引数で、それらのバインド変数に実際に「結びつける」値を 「val2 = 20」のようにセットします。 OUT変数の場合はセットする必要がないというかセットしようがないので、 「oval = -1」のように適当に流しの値を入れておけばOKです。
 実行がOKなら、カーソルのfetchbindsというメソッド (これはPython DB API 2.0で定義されているものではなく、 cx_Oracle独自のものです) を使うと、OUT変数の「バインド変数名」をキーに、 その実際の値を値にもつディクショナリ(辞書) が返ってくるので、上の「b['oval']」のようにして取り出すことができます。

セクションのサブメニューに戻る
(first uploaded 2001/07/20 last updated 2002/07/15)