[PHP] oci_bind_by_name() の maxlength パラメータ | Archive Redo Blog

Archive Redo Blog

DBエンジニアのあれこれ備忘録

OCI8 を使って Oracle の SQL を実行する際、バインド変数に値をセットするには oci_bind_by_name() 関数を使用します。

oci_bind_by_name( $stmt, ':name', $name );

この oci_bind_by_name() 関数には、 statement(OCI ステートメント)、ph_name(プレースホルダー)、variable(PHP 変数)、maxlength(バインド時の最大長)、type(抽象データ型)の5つのパラメータを指定することができますが、maxlength と type はオプションとなっており、それぞれ-1(variable の長さ)、SQL_CHR(文字列型)がデフォルト値となっています。

大概の場合、maxlength と type は省略しても支障はないため、ついつい省略してしまうことが多いのですが、省略したことが原因でしばしばトラブルを起こすこともあるので注意が必要です。


例えば、以下のストアドプロシージャの実行例で :code で表されるパラメータが OUT パラメータであった場合、

.
.
.
$sql = "BEGIN CHECK_DATA( :code ); END;";
$stmt = oci_parse( $con, $sql );
oci_bind_by_name( $stmt, ':message', $message );
oci_execute( $stmt );
.
.
.

実行時に以下のエラーが発生することがあります。

PHP Warning: oci_execute(): ORA-06502: PL/SQL: 数値または値のエラー: 文字列バッファが小さすぎます。が発生しました

OUT パラメータの場合、oci_bind_by_name() 関数でバインドするタイミングでは variable にセットした PHP 変数の値は空である可能性が高いと思います。

そのため、maxlength が過少に設定され、いざ実行した際にストアドプロシージャが OUT パラメータを返そうとすると、”文字列バッファが小さすぎます。”となるわけです。

このエラーは maxlength を明示的に指定してやることで解消します。

oci_bind_by_name( $stmt, ':code', $code, 32767 );


また、一般的に、バインド変数の最大長はデータ型ほどには気にされないと思います。

そのため、ついつい、

oci_bind_by_name( $stmt, ':id', $id, SQLT_INT );

というふうに、maxlength パラメータをうっかり飛ばしてしまうことがあるかもしれません。

この時、maxlength の位置に誤ってセットされてしまっている SQL_INT の定数値は 3 ですので、最大長 3 と指定していることになります。

そのため、3 桁までの値をセットした場合は正常に動作しますが、4 桁以上の値をセットした場合は、以下のようなエラーが発生します。

PHP Warning: oci_execute() [<a href='function.oci-execute'>function.oci-execute</a>]: ORA-01460: リクエストされた変換はできません。

このエラーは当然 maxlength を適切にセットしてやることで解消します。

oci_bind_by_name( $stmt, ':id', $id, 10, SQLT_INT );


上記の2つの例は、実行時に必ずエラーになるわけではなく、セットされる値によって発生したり発生しなかったりするものです。

そのため、特に意識してコーディングとテストを行わなければなりません。