You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP Oracle OCI插入BLOB并返回记录键时出现描述符错误咨询

PHP OCI插入BLOB并返回序列主键的问题解决

我看了你这段代码,问题其实出在返回主键的绑定类型错误上!你把返回主键的:retcol用OCI_B_BLOB类型绑定了,但FILE_KEY是序列生成的主键(应该是数值或字符串类型),和BLOB类型完全不匹配——这就是你遇到“Unable to find descriptor property”错误的根源,跟单次查询做多个操作没关系,OCI完全支持在RETURNING子句里同时返回LOB句柄和普通字段。

关键修正步骤

  1. 修正返回主键的绑定类型
    把绑定:retcol的代码,从错误的BLOB类型改成对应主键的类型:

    • 如果FILE_KEY是Oracle的NUMBER类型,用OCI_B_INT;
    • 如果是VARCHAR2类型,用OCI_B_STR;
    • 也可以省略类型参数,OCI会自动推断。

    原来的错误代码:

    if (strcmp($other_retcol,'')) {
        oci_bind_by_name($obf_parse, ":retcol", $retcol, -1, OCI_B_BLOB);
    }
    

    修正后(假设FILE_KEY是NUMBER类型):

    if (strcmp($other_retcol,'')) {
        // 20是字段最大长度,根据你的实际表结构调整
        oci_bind_by_name($obf_parse, ":retcol", $retcol, 20, OCI_B_INT);
    }
    
  2. (可选)修正输入参数绑定的引用问题
    原来绑定输入参数时直接传递数组元素的值,oci_bind_by_name需要变量引用,可能导致绑定失效,建议改成引用遍历:

    $i=0;
    foreach ($bindarr as &$bindvar) { // 加&取变量引用
        @oci_bind_by_name($obf_parse,":var${i}",$bindvar,-1);
        $i++;
    }
    unset($bindvar); // 解除引用,避免后续变量污染
    

完整修正后的ora_lob_insert方法

public function ora_lob_insert($sql,$bindarr=array(),$lobcol='',$lobvar='',$other_retcol='') {
    Global $errormess;
    $retcol=0;
    // $sql must finish "RETURNING {lob_column} INTO :mylob" - Use EMPTY_CLOB() when inserting
    if (substr_count($sql,'?') != count($bindarr)) {
        // number of ? in query string different to number of values in array
        $errormess='Error ora_bind_exec: Mismatch between query markers and bind values array!';
    }
    $i=0;
    $worked=false;
    foreach ($bindarr as $bindvar) {
        $sql=preg_replace('/\?/',":var${i}", $sql, 1);
        $i++;
    }
    if (!strcmp($other_retcol,'')) {
        $sql.=" RETURNING $lobcol INTO :mylob";
    } else {
        $sql.=" RETURNING $lobcol, $other_retcol INTO :mylob, :retcol";
    }
    $obf_parse=@oci_parse($this->connect,$sql);
    if ($obf_parse === false) {
        // Parse Failed
        $errormess='Error ora_lob_insert: Query Parse Failed!';
    }
    $myLOB = @oci_new_descriptor($this->connect, OCI_D_LOB);
    // Bind the returned Oracle LOB locator to the PHP LOB object
    @oci_bind_by_name($obf_parse, ":mylob", $myLOB, -1, OCI_B_BLOB);
    if (strcmp($other_retcol,'')) {
        // 修正:绑定主键为整数类型,调整长度适配你的表结构
        oci_bind_by_name($obf_parse, ":retcol", $retcol, 20, OCI_B_INT);
    }
    $i=0;
    foreach ($bindarr as &$bindvar) {
        @oci_bind_by_name($obf_parse,":var${i}",$bindvar,-1);
        $i++;
    }
    unset($bindvar);
    $list=array();
    $obf_exec=@oci_execute($obf_parse,OCI_DEFAULT);
    if ($obf_exec === false) {
        // Execute Failed
        $errormess='Error ora_lob_insert: Query Execution Failed!'."($sql)";
    }
    // Now save a value to the LOB
    if ( !$myLOB->save($lobvar)) {
        // On error, rollback the transaction
        oci_rollback($this->connect);
        $errormess='Error ora_lob_insert: Failed saving BLOB!';
    } else {
        // On success, commit the transaction
        oci_commit($this->connect);
        $worked=true;
    }
    @oci_free_statement($obf_parse);
    if (!strcmp($other_retcol,'')) {
        return $worked;
    } else {
        return $retcol;
    }
}

额外说明

  • 顺便帮你修正了代码里的小拼写错误:Failed savin BLOB!改成Failed saving BLOB!
  • 你的思路完全没问题:用RETURNING同时获取LOB句柄和序列主键是OCI的标准用法,不需要拆分两次查询,这次的错误只是类型绑定的低级失误。

内容的提问来源于stack exchange,提问作者Arthur Nicoll

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:35:33