Ruby/OCI8 下位API

[ Home ] [ English | Japanese ]

目次

はじめに

実装方針

クラス階層

クラスとメソッドの一覧

OCIHandle

OCI ハンドルの抽象クラスです。 クラス階層 を参照してください。

OCIHandle#attrSet(type, value)
type
属性の種類。 ハンドル及び記述子の属性を参照してください。
value
type に依存。

対応するネイティブOCI関数: OCIAttrSet

OCIHandle#attrGet(type)
type
属性の種類。 ハンドル及び記述子の属性を参照してください。
return value
type に依存。

対応するネイティブOCI関数: OCIAttrGet

OCIHandle#free()

OCI のデータ構造を明示的に解放する。

対応するネイティブOCI関数: OCIHandleFree

OCIEnv

環境ハンドル。このハンドルがすべての OCI オブジェクトの元となる。 たいていはひとつのアプリケーションにひとつのインスタンスです。

親クラス: OCIHandle

対応するネイティブOCIデータタイプ: OCIEnv

OCIEnv.create([mode])

環境ハンドルを作成する。new は呼ばないでください。

mode

OCI_DEFAULT, OCI_THREADED, OCI_OBJECT, OCI_SHARED もしくはこれらの組み合わせが指定可能です。しかし動作テストしてるのは OCI_DEFAULT のみです。デフォルト値は OCI_DEFAULT です。

OCI_THREADED: ネイティブスレッド(ruby のスレッドとは別)を使用しているとき。

OCI_OBJECT: OCI オブジェクトを使うとき指定します。しかし、今の実装では OCI オブジェクトリレーショナル関数をサポートしていませんし、計画にもはいって いません。

OCI_SHARED(Oracle 8i以降): 共有データ・モードを使用するとき指定します。

戻り値
OCIEnv のインスタンス

対応するネイティブOCI関数: OCIEnvCreate (OCIEnvCreate がないときは OCIInitializeOCIEnvInit を使用)

OCIEnv.terminate([mode])
mode
OCI_DEFAULT のみが使用できます。デフォルト値は OCI__DEFAULT です。

対応するネイティブOCI関数: OCITerminate

OCIEnv#alloc(handle)

新しい OCI ハンドルを作成します。

handle
有効な値は OCISvcCtx, OCIStmt, OCIServer, OCIServer, OCISession, OCIDescribe です。
戻り値
新しく作成されたハンドルです。

対応するネイティブOCI関数: OCIHandleAlloc

OCIEnv#logon(username, password, dbname)

オラクルにログオンします。

単純化されたログイン明示的な連結(アタッチ)及び開始セッションも参照してください。

username
ユーザ名
password
ユーザのパスワード
dbname
データベース名もしくは、nil
戻り値
OCISvcCtxのインスタンス

例:

env = OCIEnv.create()
svc = env.logon("SCOTT", "TIGER", nil)
  or
svc = env.logon("SCOTT", "TIGER", "ORCL.WORLD")

対応するネイティブOCI関数: OCILogon

OCISvcCtx

サービス・コンテキスト・ハンドル。このハンドルは他の一般的なデータ ベースインターフェースのセッションに相当します。

内部的にサーバー・ハンドルユーザ・セッション・ハンドル、 トランザクション・ハンドルの3種類のハンドルと協同して動きますが、特別な用途を除いて これらの内部ハンドルを直接あつかう必要はありません。

親クラス: OCIHandle

対応するネイティブOCIデータタイプ: OCISvcCtx

OCISvcCtx#logoff()

オラクルとの接続を切断します。

ログインするのにOCIServer#attachOCISession#begin を使った場合は、代わりにOCIServer#detachOCISession#end を用いてください。 単純化されたログイン明示的な連結(アタッチ)及び開始セッション も参照してください。

対応するネイティブOCI関数: OCILogoff

OCISvcCtx#passwordChange(username, old_password, new_password [, mode])
username
the username.
old_password
old password of the user.
new_password
new password of the user.
mode

OCI_DEFAULT or OCI_AUTH. Default value is OCI_DEFAULT.

For most cases, use default value. If you want to know detail, see "Oracle Call Interface Programmer's Guide".

correspond native OCI function: OCIPasswordChange

OCISvcCtx#commit([flags])

トランザクションを確定(コミット)します。

flags
OCI_DEFAULTもしくはOCI_TRANS_TWOPHASE。 デフォルト値はOCI_DEFAULTです。

対応するネイティブOCI関数: OCITransCommit

OCISvcCtx#rollback([flags])

トランザクションを取り消(ロールバック)します。

flags
OCI_DEFAULTのみが有効です。デフォルト値はOCI_DEFAULTです。

対応するネイティブOCI関数: OCITransRollback

OCISvcCtx#version()

get server version.

return value

string of server version. For example

Oracle8 Release 8.0.5.0.0 - Production
PL/SQL Release 8.0.5.0.0 - Production

correspond native OCI function: OCIServerVersion

OCISvcCtx#release()

get server version number and string

return value

array of number and string. For example

version_number, version_str = svc.release()
version_number is 0x8005000.
version_str is
  Oracle8 Release 8.0.5.0.0 - Production
  PL/SQL Release 8.0.5.0.0 - Production

correspond native OCI function: OCIServerVersion

Oracle 9i or later?

OCIServer

サーバー・ハンドル。OCIEnv#logonを使った場合は、このハンドルを直接使う必要はありません。 というのも、OCIEnv#logonが暗黙のうちにハンドルを生成して、OCISvcCtxに設定するからです。

親クラス: OCIHandle

対応するネイティブOCIデータタイプ: OCIServer

OCIServer#attach(dbname [, mode])

データベースに連結(アタッチ)する。

dbname
接続するデータベースの名前。ローカル接続なら nil。
mode

OCI_DEFAULTもしくはOCI_CPOOL(Oracle 9i)。デフォルト値はOCI_DEFAULTです。

この ruby モジュールは OCI の提供するコネクションプーリングをサポートしていません。 したがって、OCI_CPOOLは現在のところ無効な値です。

対応するネイティブOCI関数: OCIServerAttach

OCIServer#detach([mode])

データベースとの連結を切り放します。

mode
OCI_DEFAULTのみが有効です。デフォルト値はOCI_DEFAULTです。

対応するネイティブOCI関数: OCIServerDetach

OCIServer#version()

get server version.

return value

string of server version. For example

Oracle8 Release 8.0.5.0.0 - Production
PL/SQL Release 8.0.5.0.0 - Production

correspond native OCI function: OCIServerVersion

OCIServer#release()

get server version number and string

return value

array of number and string. For example

version_number, version_str = srv.release()
version_number is 0x8005000.
version_str is
  Oracle8 Release 8.0.5.0.0 - Production
  PL/SQL Release 8.0.5.0.0 - Production

correspond native OCI function: OCIServerVersion

Oracle 9i or later?

OCISession

サーバー・ハンドル。OCIEnv#logonを使った場合は、このハンドルを直接使う必要はありません。 というのも、OCIEnv#logonが暗黙のうちにハンドルを生成して、OCISvcCtxに設定するからです。

親クラス: OCIHandle

対応するネイティブOCIデータタイプ: OCISession

OCISession#begin(svc [, credt [, mode]])

指定されたサーバコンテキストの元で、ユーザセッションを開始します。

svc
OCISvcCtx.
credt

OCI_CRED_RDBMSもしくはOCI_CRED_EXT。 デフォルト値はOCI_CRED_RDBMSです。

OCI_CRED_RDBMSを使用する場合は、事前にOCI_ATTR_USERNAMEOCI_ATTR_PASSWORD を設定してください。

mode

OCI_DEFAULTOCI_MIGRATEOCI_SYSDBAOCI_SYSOPER、 (OCI_SYSDBA | OCI_PRELIM_AUTH)、もしくは(OCI_SYSOPER | OCI_PRELIM_AUTH)。 デフォルト値はOCI_DEFAULTです。

SYSDBA権限もしくはSYSOPER権限が必要なときは、 OCI_SYSDBAもしくはOCI_SYSOPERを使ってつださい。

対応するネイティブOCI関数: OCISessionBegin

OCISession#end(svc [, vmode])

ユーザ認証のコンテキストを終了する。

svc
OCISvcCtx.
mode
OCI_DEFAULTのみが有効です。デフォルト値はOCI_DEFAULTです。

対応するネイティブOCI関数: OCISessionEnd

OCIStmt

文ハンドル。このハンドルで SQL や PL/SQL とその属性を識別します。

SQL や PL/SQL の入出力変数の情報はバインド・ハンドルにて、 Select 文で select されるデータの情報は定義ハンドルにて 管理されます。

親クラス: OCIHandle

対応するネイティブOCIデータタイプ: OCIStmt

OCIStmt#prepare(stmt [, language [, mode]])

SQL 文を設定して、実行の準備を行います。

stmt
SQL もしくは PL/SQL 文
language
OCI_NTV_SYNTAX, OCI_V7_SYNTAX, または OCI_V8_SYNTAX。 デフォルト値はOCI_NTV_SYNTAX
mode

OCI_DEFAULT または OCI_NO_SHARING。デフォルト値はOCI_DEFAULT

OCI_NO_SHARING を指定すると、この文のついてのみ、共有データ・モード を無効にします。

対応するネイティブOCI関数: OCIStmtPrepare

OCIStmt#defineByPos(position, type [, length [, mode]])

select 文の実行でとりだされるデータのデータタイプを定義します。 select 文からデータを取り出す前に、すべてのカラムの定義を行わないといけません。

position
カラムの位置を指定します。1 から数えます。
type
カラムの種類を指定します。 StringFixnumIntegerFloatTimeOraDateOraNumberOCI_TYPECODE_RAW が指定可能です。
length
第二引数が
  • String もしくは OCI_TYPECODE_RAW のとき、 取り出すデータの最大長
  • それ以外の場合は、 無視されます。
mode
OCI_DEFAULT, もしくは OCI_DYNAMIC_FETCH. しかし今の実行で有効なのは、OCI_DEFAULT のみです。 デフォルト値は OCI_DEFAULT です。
戻り値
新規に作成された定義ハンドル

対応するネイティブOCI関数: OCIDefineByPos

OCIStmt#bindByPos(position, type [, length [, mode]])

バインド変数のデータタイプを位置指定で定義します。

position
バインド変数の位置を指定します。
type
バインド変数の種類を指定します。 StringFixnumIntegerFloatTimeOraDateOraNumberOCI_TYPECODE_RAW が指定可能です。
length
第二引数が
  • String もしくは OCI_TYPECODE_RAW のとき、 取り出すデータの最大長
  • それ以外の場合は、 無視されます。
mode
OCI_DEFAULT, もしくは OCI_DATA_AT_EXEC|. しかし今の実行で有効なのは、OCI_DEFAULT のみです。 デフォルト値は OCI_DEFAULT です。
戻り値
新規に作成されたバインド・ハンドル

対応するネイティブOCI関数: OCIBindByPos

OCIStmt#bindByName(name, type [, length [, mode]])

バインド変数のデータタイプを名前で定義します。

name
バインド変数の名前を指定します。
type
バインド変数の種類を指定します。 StringFixnumIntegerFloatTimeOraDateOraNumberOCI_TYPECODE_RAW が指定可能です。
length
第二引数が
  • String もしくは OCI_TYPECODE_RAW のとき、 取り出すデータの最大長
  • それ以外の場合は、 無視されます。
mode
OCI_DEFAULT, もしくは OCI_DATA_AT_EXEC|. しかし今の実行で有効なのは、OCI_DEFAULT のみです。 デフォルト値は OCI_DEFAULT です。
戻り値
新規に作成されたバインド・ハンドル

stmt = env.alloc(OCIStmt)
stmt.prepare("SELECT * FROM EMP
               WHERE ename = :ENAME
                 AND sal > :SAL
                 AND hiredate >= :HIREDATE")
b_ename = stmt.bindByName(":ENAME", String, 10)
b_sal = stmt.bindByName(":SAL", Fixnum)
b_hiredate = stmt.bindByName(":HIREDATE", OraDate)

対応するネイティブOCI関数: OCIBindByName

OCIStmt#execute(svc [, iters [, mode]])

文と指定されたサービス・コンテキスト・ハンドルのもとで実行します。

svc
サービス・コンテキスト・ハンドル
iters

実行する回数を指定します。

select 文に対して、OCIStmt#defineByPosで定義してないカラムがあり、 正の値のとき、例外が起こります。0 のときは例外が起こります。どちらにし ても、OCIStmt#fetchを呼ぶ前にはすべてのカラムが定義してないといけ ません。

非select文に対しては正の値を指定してください。

デフォルト値は、select 文に対しては 0, それ以外は 1 です。

note: 現在の実装は配列のフェッチやバッチモードをサポートしていません。 したがって有効な値は 0 か 1 です。

mode

OCI_DEFAULT, OCI_BATCH_ERRORS, OCI_COMMIT_ON_SUCCESS, OCI_DESCRIBE_ONLY, OCI_EXACT_FETCH, OCI_PARSE_ONLY, これらの任意の組み合わせ、もしくは OCI_STMT_SCROLLABLE_READONLY. デフォルト値はOCI_DEFAULTです。

OCI_BATCH_ERRORSOCI_STMT_SCROLLABLE_READONLYは現在の実行では サポートされていません。

対応するネイティブOCI関数: OCIStmtExecute

OCIStmt#fetch([nrows [, orientation [, mode]]])

select 文より選択結果を取り出します。 選択された値は前もって定義した定義ハンドル に設定されます。

nrows

フェッチする行数を指定します。0 の場合、カーソルが取り消されます。 デフォルト値は 1 です。

配列のフェッチがサポートされてないので、有効な値は 0 と 1 のみです。

orientation
フェッチする方向を指定します。OCI_FETCH_NEXTのみが有効です。 デフォルト値はOCI_FETCH_NEXTです。
mode
OCI_DEFAULTのみが有効です。 デフォルト値はOCI_DEFAULTです。
戻り値
事前に定義された定義ハンドルの配列を戻します。 データがないときは nil が返ります。

対応するネイティブOCI関数: OCIStmtFetch

OCIStmt#paramGet(position)

実行された select 文のカラム情報を取得します。 カラムタイブが不明なテーブルの selectを参考してください。

position
パラメータを取得するカラムの位置を指定します。1 より数えます。
戻り値
新規に作成された読み取り専用パラメータ記述子

対応するネイティブOCI関数: OCIParamGet

OCIDefine

定義ハンドル。OCIStmt#defineByPos により生成され、SELECT 文から値を得るには このハンドルを経由します。

親クラス: OCIHandle

対応するネイティブOCIデータタイプ: OCIDefine

OCIDefine#get()

SELECT された値を得ます。

return value
取得されたデータ。データタイプは OCIStmt#defineByPos の第二引数で設定したものと対応します。

対応するネイティブOCI関数: なし

OCIBind

バインドハンドル。OCIStmt#bindByPosOCIStmt#bindByName により生成されます。

親クラス: OCIHandle

対応するネイティブOCIデータタイプ: OCIBind

OCIBind#get()

OCI コールのよって設定されたバインド値を取得します。

戻り値
バインド値。データタイプは OCIStmt#bindByPosOCIStmt#bindByName の第二引数で設定したものと対応します。

対応するネイティブOCI関数: なし

OCIBind#set(value)

OCI コール経由でオラクルにわたすバインド値を設定します。

value
バインドハンドルに設定する値。データタイプは OCIStmt#bindByPosOCIStmt#bindByName の第二引数に設定したものと対応してないといけません。

対応するネイティブOCI関数: なし

OCIDescribe

記述ハンドル。明示的な記述を行うときに使用されます。

親クラス: OCIHandle

対応するネイティブOCIデータタイプ: OCIDescribe

例:

dsc = env.alloc(OCIDescribe)
dsc.describeAny(svc, "EMP", OCI_PTYPE_TABLE)
parm = dsc.attrGet(OCI_ATTR_PARAM)
...get various information from parm...

このクラス経由で OCISvcCtx より OCIParam を取得する。

OCIDescribe#describeAny(svc, name, type)

オラクルのスキーマオブジェクト、たとえば、テーブル、ビュー、シノニム、 プロシージャ、ファンクション、パッケージ、シーケンス等のさまざまな情 報を得る。使い方はOCIDescribeを参照してください。

svc
調べたいオブジェクトの所属するサービス・コンテキスト
name
調べたいオブジェクトの名前
type
調べたいオブジェクトの種類
  • テーブルにはOCI_PTYPE_TABLE
  • ビューにはOCI_PTYPE_VIEW
  • プロシージャにはOCI_PTYPE_PROC
  • ファンクションにはOCI_PTYPE_FUNC
  • パッケージにはOCI_PTYPE_PKG
  • タイプにはOCI_PTYPE_TYPE
  • シノニムにはOCI_PTYPE_SYN
  • シーケンスにはOCI_PTYPE_SEQ
  • スキーマにはOCI_PTYPE_SCHEMA
  • データベースにはOCI_PTYPE_DATABASE
  • 種類が不明な場合にはOCI_PTYPE_UNK

対応するネイティブOCI関数: OCIDescribeAny

注意: Linux 版の Oracle 8.0.5 でこのメソッドを使用するときは、 OCIEnv.create を OCI_OBJECT 付きで呼んでください。さもないと segmentation fault が起きます。このバグは 8.0.6 以降で修正されています。

OCIDescriptor

OCI 記述子の抽象クラス

OCIDescriptor#attrGet(type)
type
取得する属性の種類
return value
引数の type に依存する。

ハンドル及び記述子の属性 を参照。

OCIDescriptor#free()
このオブジェクトに付随する OCI のデータ構造を明示的に解放する。 ruby のオブジェクトそのものは解放しない。

OCIParam

super class: OCIDescriptor

OCIError

OCIError#code()
OCIError#codes()
OCIError#message()
OCIError#messages()
OCIError#parseErrorOffset()
OCIError#sql()
(Oracle 8.1.6 or later)

OraDate

date and time between 4712 B.C. and 9999 A.D.

OraDate.new([year [, month [, day [, hour [, min [,sec]]]]]])
OraDate.now()
OraDate#to_s()
OraDate#to_a()
OraDate#year
OraDate#month
OraDate#day
OraDate#hour
OraDate#minute
OraDate#second
OraDate#trunc()

OraNumber

This is not a numeric class, so algebra operations and setter methods are not permitted, but a place to hold fetched date from Oracle server.

In fact as matter, this is a test class to check the algorithm to convert Oracle internal number format to Ruby's number, which is internally used by, for example, OCIStmt#attrGet(OCI_ATTR_MIN).

OraNumber.new()
OraNumber#to_i()
OraNumber#to_f()
OraNumber#to_s()

ハンドル及び記述子の属性

属性を設定するには、OCIHandle#attrSet もしくは OCIDescriptor#attrSet を、 属性値を得るには、OCIHandle#attrGet もしくは OCIDescriptor#attrGet を使用してください。

詳細は "Oracle Call Interfaceプログラマーズ・ガイド" を見てください。マニュアルを持ってない場合は、 OTN Japan から PDF ドキュメントを取得できます。

OCI_ATTR_SERVER
OCISvcCtxOCIServer を設定する。 明示的な連結(アタッチ)及び開始セッション を参照。
OCI_ATTR_SESSION
OCISvcCtxOCISession を設定する。 明示的な連結(アタッチ)及び開始セッション を参照。
OCI_ATTR_ROW_COUNT
OCIStmt より選択された行数を取得する。
OCI_ATTR_PREFETCH_ROWS
OCIStmt にプリフェッチ行を設定する。デフォルト値は 1。
OCI_ATTR_PREFETCH_MEMORY
OCIStmt にプリフェッチで使用する最大メモリを設定する。 デフォルト値は 0。0 の場合制限なしで、プリフェッチで使用するメモリは OCI_ATTR_PREFETCH_ROWS のみで制限される。
OCI_ATTR_PARAM_COUNT
OCIStmt より選択リストの列数、または OCIDescribe よりパラメータの数を取得する。
OCI_ATTR_ROWID

OCIStmt より現在のカーソル位置の ROWID を得る。 この仕様はまだ FIX していません。 ROWID サポートを参照のこと。

(Oracle 9i or later.)

OCI_ATTR_USERNAME
OCISession にユーザ名を設定する。 明示的な連結(アタッチ)及び開始セッション を参照。
OCI_ATTR_PASSWORD
OCISession にパスワードを設定する。 明示的な連結(アタッチ)及び開始セッション を参照。
OCI_ATTR_STMT_TYPE

OCIStmt よりステートメントの種類を取得する。

戻り値は OCI_STMT_SELECT, OCI_STMT_UPDATE, OCI_STMT_DELETE, OCI_STMT_INSERT, OCI_STMT_CREATE OCI_STMT_DROP, OCI_STMT_ALTER, OCI_STMT_BEGIN, OCI_STMT_DECLARE のどれか。

COI_ATTR_NUM_COLS
テーブルまたはビューの OCIParam より列数を取得する。
OCI_ATTR_LIST_COLUMNS
get OCIParam of column list from OCIParam of table or view.
OCI_ATTR_CLUSTERED
get whether the table is clusterd or not from OCIParam of table.
OCI_ATTR_PARTITIONED
get whether the table is partitioned or not from OCIParam of table.
OCI_ATTR_LIST_ARGUMENTS
get OCIParam of argument list from OCIParam of procedure, or function.
OCI_ATTR_LINK
get the database link name of the synonym translation from OCIParam of synonym.
OCI_ATTR_MIN
get minimum value from OCIParam of sequecne.
OCI_ATTR_MAX
get maximum value from OCIParam of sequecne.
OCI_ATTR_INCR
get increment value from OCIParam of sequecne.
OCI_ATTR_CACHE
get number of sequence numbers cached from OCIParam of sequecne.
OCI_ATTR_ORDER
get whether the sequence is orderd or not from OCIParam of sequecne.
OCI_ATTR_HW_MARK
get high-water mark from OCIParam of sequecne.
OCI_ATTR_NUM_PARAMS
get the number of parameters from OCIParam.
OCI_ATTR_OBJID
get object or schema Id from OCIParam.
OCI_ATTR_PTYPE
get the type of OCIParam. Returend value is OCI_PTYPE_TABLE, OCI_PTYPE_VIEW, OCI_PTYPE_PROC, OCI_PTYPE_FUNC, OCI_PTYPE_PKG, OCI_PTYPE_TYPE, OCI_PTYPE_SYN, OCI_PTYPE_SEQ, OCI_PTYPE_COL, OCI_PTYPE_ARG, OCI_PTYPE_LIST, OCI_PTYPE_TYPE_ATTR, OCI_PTYPE_TYPE_COLL, OCI_PTYPE_TYPE_METHOD, OCI_PTYPE_TYPE_ARG, OCI_PTYPE_TYPE_RESULT, OCI_PTYPE_SCHEMA, or OCI_PTYPE_DATABASE.
OCI_ATTR_PARAM
get a OCIParam descriptor from OCIDescribe handle.
OCI_ATTR_IS_TEMPORARY
get whether the table is temporary or not from OCIParam of table.
OCI_ATTR_IS_INVOKER_RIGHTS
get whether the the procedure or function is invoker-rights or not from OCIParam of procedure, or function.
OCI_ATTR_OBJ_NAME
Database name or object name from OCIParam.
OCI_ATTR_OBJ_SCHEMA
get schema name where the object is located from OCIParam.
OCI_ATTR_OBJ_ID
get object or schema Id from OCIParam.
OCI_ATTR_STATEMENT
get the text of the SQL statement prepared in a OCIStmt.
OCI_ATTR_MAXCHAR_SIZE

get or set the maxinum number of characters from OCIDefine or OCIBind, rather than the number of bytes.

Don't set larger number than previous one.

(Oracle 9i or later?)

OCI_ATTR_CURRENT_POSITION
get the current position of result set from OCIStmt for scrollable cursors. Scrollable cursors is not supported by this ruby interface. I hope someone implement it.
OCI_ATTR_ROWS_FETCHED
get the number of rows that were successfully fetched from OCIStmt.
OCI_ATTR_DATA_SIZE
get the maximum size of the column, argument and so on in bytes form OCIParam. It returns 22 for NUMBERs.
OCI_ATTR_DATA_TYPE
get the data type of the column, argument and so on from OCIParam.
OCI_ATTR_NAME
get the name string from OCIParam.
OCI_ATTR_PRECISION
get the precision of number from OCIParam.
OCI_ATTR_SCALE
get the scale of number from OCIParam.
OCI_ATTR_IS_NULL
get whether the null values are permitted or not from OCIParam of column or arugment.
OCI_ATTR_CHAR_USED

get whether the type of length semantics from OCIParam of column. If true, in characters. If false, in bytes.

(Oracle 9i or later?)

OCI_ATTR_CHAR_SIZE

get the maximum size of the column, argument and so on in characters form OCIParam. To get in bytes, use OCI_ATTR_DATA_SIZE.

(Oracle 9i or later?)

一行 select

select 文を実行して、結果を得るには、OCIStmt#defineByPos を実行 して取得するデータの種類を定義する必要があります。select した結果は、 カラムを定義した時に得られる定義ハンドルでもって知るこ とができます。

require 'oci8'

# 環境ハンドル作成
env = OCIEnv.create()
# オラクルへログオン
svc = env.logon("SCOTT", "TIGER", nil)
# 文ハンドルの準備
stmt = env.alloc(OCIStmt)
stmt.prepare("SELECT TO_CHAR(SYSDATE, 'YYYY/MM/DD') FROM DUAL")
# 一番目のカラムを 幅 10文字の String として定義
col1 = stmt.defineByPos(1, String, 10)
# svc の元で一回実行
stmt.execute(svc, 1)
# 定義ハンドルより結果を取得。
p col1.get()
# 文ハンドルを解放
stmt.free()
# ログオフ
svc.logoff()

OCIStmt#defineByPos の第二引数に指定できるのは、以下の7種です。

String を指定したときは、さらに長さの指定が必要です。

stmt.defineByPos(1, String, 100)
stmt.defineByPos(2, Fixnum)
stmt.defineByPos(3, Integer)
stmt.defineByPos(4, Float)
stmt.defineByPos(5, Time)
stmt.defineByPos(6, OraDate)
stmt.defineByPos(7, OraNumber)

複数行の select

一行以上の行を取得するには、OCIStmt#fetch を使用します。

OCIStmt#fetch はデータが取得できたときは事前に OCIStmt#defineByPos で定義した定義ハンドルの配列 を返します。データが終わりのときは nil を返します。

require 'oci8'

# 環境ハンドル作成
env = OCIEnv.create()
# オラクルへログオン
svc = env.logon("SCOTT", "TIGER", nil)
# 文ハンドルの準備
stmt = env.alloc(OCIStmt)
stmt.prepare("SELECT ename, sal FROM emp")
stmt.defineByPos(1, String, 10)
stmt.defineByPos(2, Fixnum)
# svc の元で実行。fetch を使うときは、第二引数は不要。
stmt.execute(svc)
# fetch を繰り返す。
while result = stmt.fetch()
  p result[0].get() # 1番目のカラム
  p result[1].get() # 2番目のカラム
end
# 文ハンドルを解放
stmt.free()
# ログオフ
svc.logoff()

カラムタイブが不明なテーブルの select

select 文で返されるデータの数とデータタイプは 読み取り専用パラメータ記述子を経由して動的に知ることが できます。

あとは、動的に得たデータタイプも元に、select 結果のデータタイプを定義 すれば、結果を得ることができます。

require 'oci8'

env = OCIEnv.create()
svc = env.logon("SCOTT", "TIGER", nil)
stmt = env.alloc(OCIStmt)
stmt.prepare("SELECT * FROM emp")
stmt.execute(svc)
# select 文を実行したあとに、
# 1 からパラメータの数までループを回す。
num_of_columns = stmt.attrGet(OCI_ATTR_PARAM_COUNT)
1.upto(num_of_columns) do |i|
  # i 番目の読み取り専用パラメータ記述子を得る。
  parm = stmt.paramGet(i)
  # 各パラメータを得る。
  name = parm.attrGet(OCI_ATTR_NAME)
  datatype = parm.attrGet(OCI_ATTR_DATA_TYPE)
  datasize = parm.attrGet(OCI_ATTR_DATA_SIZE)
  scale = parm.attrGet(OCI_ATTR_SCALE)
  precision = parm.attrGet(OCI_ATTR_PRECISION)

  # datatype 毎に、カラム定義の種類を変える。
  case datatype
  when OCI_TYPECODE_VARCHAR
    stmt.defineByPos(i, String, datasize)
  when OCI_TYPECODE_CHAR
    stmt.defineByPos(i, String, datasize)
  when OCI_TYPECODE_RAW
    stmt.defineByPos(i, OCI_TYPECODE_RAW, datasize)
  when OCI_TYPECODE_NUMBER
    if scale == 0
      # 整数の場合
      if precision <= 9 # Fixnum の精度 (31 ビットと仮定)
        stmt.defineByPos(i, Fixnum)
      else
        stmt.defineByPos(i, Integer)
      end
    else
      # 小数点以下がある場合
      if precision < 15 # Float の精度
        stmt.defineByPos(i, Float)
      else
        stmt.defineByPos(i, OraNumber)
      end
    end
  when OCI_TYPECODE_DATE
    stmt.defineByPos(i, OraDate)
    # or stmt.defineByPos(i, Time)
  else
    raise "unsupported datatype: #{datatype}"
  end

  print(", ") if i != 1
  print(name)
end
print("\n")

while result = stmt.fetch()
  # OCI は 1 から数え、配列は 0 から数える。
  0.upto(num_of_columns - 1) do |i|
    print(", ") if i != 0
    print(result[i].get())
  end
  print("\n")
end
stmt.free()
svc.logoff()

入力用バインド変数の使用

バインド変数からの値の取得および設定は、バインド・ハンドル 経由で行います。バインド・ハンドルの使用方法は値の set が可能なことを 除いて定義ハンドルと同じです。

OCIStmt#bindByPos の例:

stmt = env.alloc(OCIStmt)
stmt.prepare("SELECT sal FROM emp WHARE ename = :1")
stmt.defineByPos(1, Fixnum)
stmt.bindByPos(1, String, 20).set("SMITH")
stmt.execute(svc)

OCIStmt#bindByName の例:

stmt = env.alloc(OCIStmt)
stmt.prepare("SELECT sal FROM emp WHARE ename = :ename")
stmt.defineByPos(1, Fixnum)
stmt.bindByName(":ename", String, 20).set("SMITH")
stmt.execute(svc)

準備済み文ハンドルに対して、バインド・ハンドルに値を設定して実行を繰り返 すこともできます。

例:

stmt.prepare("INSERT INTO emp(ename, sal) VALUES(:ename, :sal)")
bind_ename = stmt.bindByName(":ename", String, 20)
bind_sal = stmt.bindByName(":sal", Fixnum)
for line in ARVF
  ename, sal = line.split(",")
  bind_ename.set(ename)
  bind_sal.set(sal.to_i)
  stmt.execute(svc)
end

バインド・ハンドルは文ハンドルが解放されるか、再度 prepare するまで解放 されないので、ループ内でバインド・ハンドルを作成しないで下さい。

悪い例:

stmt.prepare("INSERT INTO emp(ename, sal) VALUES(:ename, :sal)")
for line in ARVF
  ename, sal = line.split(",")
  stmt.bindByName(":ename", String, 20).set(ename) # 悪い例
  stmt.bindByName(":sal", Fixnum).set(sal.to_i) # 悪い例
  stmt.execute(svc)
end

出力用バインド変数の使用

PL/SQL ブロックから値を取り出すには、バインド変数をバインドしたあと、 バインド・ハンドルより、OCIBind#get で取り出します。 バインドのやりかたは入力用と同じです。

例:

stmt.prepare("BEGIN :foo = BAR_FUNCTION(:baz); END;")
foo = stmt.bindByName(":foo", String, 30)
baz = stmt.bindByName(":baz", String, 30)
baz.set("BAZOON") # 入力用ハンドルに値を設定
stmt.execute(svc)
p foo.get() # 出力用ハンドルより値を取得

エラーメッセージの取得

require 'oci8'

begin
  env = OCIEnv.create()
  svc = env.logon("SCOTT", "TIGER", nil)
  stmt = env.alloc(OCIStmt)
  stmt.prepare("select * from table_name_which_does_not_exist")
  stmt.execute(svc)
rescue OCIError
  print "Error code is " + $!.code.to_s + ".\n"
  print $!.message + "\n"
  offset = $!.parseErrorOffset
  if ! offset.nil?
    if $!.respond_to?("sql")
      # Oracle 8.1.6 or later.
      print "sql is: " + $!.sql + "\n"
      print "error at" + " " * offset + "^here\n"
    else
      print "error at " + offset.to_s + "\n"
    end
  end
ensure
  stmt.free() if ! stmt.nil?
  svc.logoff() if ! svc.nil?
  env.free if ! env.nil?
end

SYSDBA 権限で接続

require 'oci8'

username = "SYS"
password = "CHANGE_ON_INSTALL"
dbname = nil
privilege = OCI_SYSDBA

env = OCIEnv.create()
srv = env.alloc(OCIServer)
srv.attach(dbname)
svc = env.alloc(OCISvcCtx)
svc.attrSet(OCI_ATTR_SERVER, srv)
auth = env.alloc(OCISession)
auth.attrSet(OCI_ATTR_USERNAME, username)
auth.attrSet(OCI_ATTR_PASSWORD, password)
auth.begin(svc, OCI_CRED_RDBMS, privilege)
svc.attrSet(OCI_ATTR_SESSION, auth)
... do SYSDBA jobs ...
auth.end(svc)
srv.detach()
svc.free()
env.free()

ROWID サポート

ROWID記述子(OCIRowid)を追加したので、この節は書き直します。

補遺

共有データ・モード
共有メモリを使って他のプロセスと SQL の文コンテキストを共有します。 同じ SQL 文を発行しているプロセスが多々ある場合、それらの SQL 文 のコンテキストが共有され、全体で見たメモリが少なくなります。 (ということをマニュアルに書いてあったけど、確認してません。m(__)m)
単純化されたログイン

シングルユーザ・シングルセッションのとき使用します。 明示的な連結(アタッチ)及び開始セッションも見てください。

例:

env = OCIEnv.create()
svc = env.logon(username, password, dbname)

To logoff:

svc.logoff()
明示的な連結(アタッチ)及び開始セッション

複数のセッション・複数の接続を使用するとき、または、 SYSDBA権限、SYSOPER権限が必要なときに使用します。 単純化されたログインも見てください。

For example:

# connect as SYSDBA
env = OCIEnv.create()
svc = env.alloc(OCISvcCtx)
srv = env.alloc(OCIServer)
srv.attach(dbname)
svc.attrSet(OCI_ATTR_SERVER, srv)
auth = env.alloc(OCISession)
auth.attrSet(OCI_ATTR_USERNAME, username)
auth.attrSet(OCI_ATTR_PASSWORD, password)
auth.begin(svc, OCI_CRED_RDBMS, OCI_SYSDBA)
svc.attrSet(OCI_ATTR_SESSION, auth)

To logoff:

srv.detach()
auth.end(svc)
svc.free()