【问题标题】:Handle a PL/SQL function returning a record in PHP处理在 PHP 中返回记录的 PL/SQL 函数
【发布时间】:2014-12-17 22:45:04
【问题描述】:

我一直在网上寻找答案,但我没有找到答案,所以我在这里。

我有一个 PL/SQL 函数返回一条记录:

create or replace package pck_test is
    TYPE coord_geo is record (coord_x float, coord_y float);
    function ArrondiGeo(coord_x float, coord_y float) return coord_geo;
end pck_test;
/

create or replace package body pck_test is
    FUNCTION ArrondiGeo(coord_x FLOAT,coord_y FLOAT) RETURN coord_geo
    IS
        temp_x FLOAT(24);
        temp_y FLOAT(24);
        rec_coord coord_geo;
    BEGIN
        temp_x := ROUND(coord_x,4)/5;
        temp_y := ROUND(coord_y,4)/5;

        temp_x := ROUND((temp_x*5),3);
        temp_y := ROUND((temp_y*5),3);

        rec_coord.coord_x := temp_x;
        rec_coord.coord_y := temp_y;

        RETURN rec_coord;
    END;
END pck_test;
/

我想在 PHP 函数中使用它,但我真的不知道如何......

我试过了,但它不起作用:

public function get_tronc($x,$y)
    {
        $q = oci_parse($this->_db, 'begin :r := pck_test.ArrondiGeo(:x,:y); end;');
        oci_bind_by_name($q, ':x', $x);
        oci_bind_by_name($q, ':y', $y);
        oci_bind_by_name($q, ':r', $r);
        oci_execute($q);

        return $r;
    }

错误是:

Warning: oci_execute(): ORA-06550: line 1, column 13: PLS-00382: expression is of wrong type ORA-06550: line 1, column 7: PL/SQL: Statement ignored in /users/info/il3/jboeglin/Bureau/BDD/site/models/userManager.php on line 77 

所以这是一个自我解释的错误,但我仍然不知道如何使用它。

谢谢。

【问题讨论】:

    标签: php plsql record


    【解决方案1】:

    对于命名数据类型,您可能需要绑定指定SQLT_NTY 类型的参数:

        $r = oci_new_collection($this->db, 'COORD_GEO');
        oci_bind_by_name($q, ':r', $r, -1, SQLT_NTY);
        ...
        oci_execute($q);
    
        // do whatever you need with your data
        $data = $elem = $collection->getElem(1);
    
        // then discard it
        $r->free();
    

    详见oci_bind_by_name的手册


    对于普通 PL/SQL 记录,您可能不走运:根据Oracle's documentation,您不能使用OCI 来获取记录。从 Oracle 11g 开始:

    以下两种类型是 PL/SQL 内部的,不能由 OCI 作为值返回:

    • 布尔值,SQLT_BOL
    • 记录,SQLT_REC

    如果这是正确的(我不是普通的 PHP 用户),您可能必须在 PL/SQ 级别包装您的函数:

    • 或者,在具有所需数量的OUT 参数的过程中;
    • 或者,根据您的需要,在表格函数中

    为了完整起见,请注意Oracle 12c + OCI8 2.0.7 remove the restriction that had previously not allowed to return a boolean value

    【讨论】:

    • 我试过了,但我得到了:警告:oci_bind_by_name(): Unable to find collection property in /users/info/il3/jboeglin/Bureau/BDD/site/models/userManager.php on line 76警告:oci_execute(): ORA-01008: 并非所有变量都绑定在第 77 行的 /users/info/il3/jboeglin/Bureau/BDD/site/models/userManager.php 中
    • @Jérôme 要使用SQLT_NTY,您需要将变量初始化为OCI-Collection。我已经编辑了我的答案(我能记住的最好的答案),向您展示如何做到这一点。
    • 谢谢,我会尝试的,即使它正在使用过程
    【解决方案2】:

    谢谢你的回答,我试过 SQLT_NTY 但它不起作用可能是因为 OCI 不能像你说的那样返回记录,... 我将尝试查看一个表函数。

    编辑:我终于使用了 PROCEDURE

    create or replace package pck_test is
    
    PROCEDURE ArrondiGeo(coord_x IN FLOAT,coord_y IN FLOAT,temp_x OUT FLOAT,temp_y OUT FLOAT);
    
    end pck_test;
    /
    
    create or replace package body pck_test is
        PROCEDURE ArrondiGeo(coord_x IN FLOAT,coord_y IN FLOAT,temp_x OUT FLOAT,temp_y OUT FLOAT)
        IS
        BEGIN
            temp_x := ROUND(coord_x,4)/5;
            temp_y := ROUND(coord_y,4)/5;
    
            temp_x := ROUND((temp_x*5),3);
            temp_y := ROUND((temp_y*5),3);
        END;
    END pck_test;
    

    /

    还有这个 php 函数:

    public function get_tronc($x,$y)
    {
        $q = oci_parse($this->_db, 'begin pck_test.ArrondiGeo(:x,:y,:xm,:ym); end;');
        oci_bind_by_name($q, ':x', $x);
        oci_bind_by_name($q, ':y', $y);
        oci_bind_by_name($q, ':xm', $xm,40);
        oci_bind_by_name($q, ':ym', $ym,40);
        oci_execute($q);
    
        $r=array($xm,$ym);
    
        return $r;
    }
    

    【讨论】:

      猜你喜欢
      • 2016-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-06
      • 2018-04-10
      • 1970-01-01
      • 1970-01-01
      • 2013-02-26
      相关资源
      最近更新 更多