応用orafetch

Oraフェチになるべく運命づけられた皆様、よくぞおいで下さいました。 まず、Oraフェチになるためにはorafetchを極めなくてはいけません。
なりたくない、ですって?ちょっとそこに座りなさい!
シャキーン(目がキラリ)

ピシピシ!言う通りになさいませんと血の雨が降りますわよ! (こらこらこら)

あー、これまでに見てきたOratclのコマンド体系は、 OracleのクライアントAPIであるOracle Call Interface(OCI) に忠実に基づいたもので、 PythonのDCOracleライブラリやPHPのOCIエクステンションとも似通った部分があります。 問い合わせ結果を1行ずつ取得するorafetchコマンドもその一環なのですが、 Oratcl独自の拡張機能を使いこなせばより簡単にコードを書くことができます。

まず、ここまでのまとめということで、 SELECT文を発行し結果を受け取るごく普通なサンプルを下に載せます。

package require Oratcl

button .cmda -text Connect -command connect_test
button .cmde -text Quit -command exit
pack .cmda .cmde -side left

proc connect_test {} {
    global oramsg
    set con [oralogon PO88/PO88]
    set st [oraopen $con]

    orasql $st "SELECT PARTS_CLASS, PARTS_CODE, NAME FROM PARTS
                  WHERE NAME LIKE '%テイコウ%'"
    if {[oramsg $st rc] != 0} {
        tk_messageBox -message "Ootto! ERRCODE=[oramsg $st rc]"
    } else {
        set result {}
        while {[oramsg $st rc] == 0} {
            set b [orafetch $ora]
            lappend result "[lindex $b 0]-[lindex $b 1]\t[lindex $b 2]"
        }
        tk_messageBox -title "Result" -message [join $result "\n"]
    }
    oraclose $st
    oralogoff $con
}
# end.

上のようにorafetchを引数1個(カーソルID)で使うと、 行全体を各カラムの値を連結したリストとして返してきます。 しかし、問い合わせ結果は普通、カラムの値ごとに別の目的で使うので、 いずれlindexコマンドで分解しなければならず、 これはかなりパフォーマンス的に無駄が多いですね。 というわけで、次のような拡張機能があります。

●orafetchの繰り返し処理を使う
上とよく似たサンプルです。どこが違うか分かりますか?

package require Oratcl

button .cmda -text Connect -command connect_test
button .cmde -text Quit -command exit
pack .cmda .cmde -side left

proc connect_test {} {
    global oramsg
    set con [oralogon PO88/PO88]
    set st [oraopen $con]
    orasql $st "SELECT PARTS_CLASS, PARTS_CODE, NAME FROM PARTS
                  WHERE NAME LIKE '%テイコウ%'"
    if {[oramsg $st rc] != 0} {
        tk_messageBox -message "Ootto! ERRCODE=[oramsg $st rc]"
    } else {
        set result {}
        orafetch $ora -datavariable row -command {
          lappend result "[lindex $row 0]-[lindex $row 1]\t[lindex $row 2]" }
        tk_messageBox -title "Result" -message [join $result "\n"]
    }
    oraclose $st
    oralogoff $con
}
# end.

もっとも大きな、というか唯一の違いは、while文がなくなって、 orafetchが1回しか呼ばれていないことです。 複数行を返すSELECT文に対しorafetchが1回でよい代わりに、 引数で何やらコマンドめいたブロックがくっついています。

  orafetch $ora -datavariable row -command {
    lappend result "[lindex $row 0]-[lindex $row 1]\t[lindex $row 2]" }
なんとなく分かると思いますが、このorafetchは、 SELECT文が返す結果を1行ずつ読みながら、 変数rowに値を格納しつつ、-commandで指定したコマンドを実行します。
また、こんな書き方もできます。
  orafetch $ora -dataarray row -indexbyname -command {
    lappend result "$row(PARTS_CLASS)-$row(PARTS_CODE)\t$row(NAME)" }
-datavariableの代わりに-dataarrayを使えば、行データをリストではなく配列 (連想配列)に格納できます。
そのときに-indexbynameを指定すれば連想配列のキーは列名、 -indexbynumberを指定すれば連想配列のキーは行番号になります。

拡張レビュー分室 top
(first uploaded 2001/03/19 last updated 2012/05/27, MISUMI URANO)