oci_bind_by_name であったトラブル

投稿者: | 2018年3月20日

Windows Server 2008上のphp5.5でOracle 11gを扱うという今が2018年か疑わしくなるような環境で開発をしたのですが、その際にoci_bind_by_nameに関するトラブルがあったので記述しておきます。

このプロジェクトは、Webから入力される情報を登録することになりますので、DBに登録するSQLの作成にはプレースホルダを使うことにしました。
当初のプログラムは次のようになります。

foreach($columns as $name => $value){
    oci_bind_by_name($stid, ":" . $name . '_bv', $value);
}

$columns連想配列にセットされているのはカラム名と値です。
これで生成されたSQLを実行すると、次のようなエラーが表示されました。

ORA-01461: LONG値はLONG列にのみバインドできます。

LONGってでかい整数のはずなので、そんなのセットしていないのにな・・・とさんざん悩みました。
いろいろコーディングを試したところ、次のように書くとエラーが発生しないことが分かりました。

oci_bind_by_name($stid, ':name_bv', $columns['name']);

foreachで回すと駄目なのに、直接配列をしていすればうまくいくのです。
怪しい点に気づいたのは oci_bind_by_name のマニュアルページを調べたときでした。
第三引数が参照型になっているんですよね。

仮説ですが、foreachでセットされる$valueはポインター的な値が入っており、それがoci_bind_by_nameで使われてしまうのではないのかと考えました。
そこでコーディングを下記のようにしました。

foreach($columns as $name => $value){
    oci_bind_by_name($stid, ":" . $name . '_bv', $columns[$name]);
}

これならLong値のエラーが発生すること無く動作するようになりました。
釈然とはしませんが、動いてよかったです!