Handle a PL/SQL function returning a record in PHP

女生的网名这么多〃 提交于 2019-12-14 00:41:48

问题


I've been looking on the Internet and I didn't find an answer so here I am.

I've a PL/SQL function returning a record :

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;
/

And I want to use it in a PHP function but I don't really know how ...

I tried this but it doesn't work :

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;
    }

The error is :

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 

So that's a self explaining error but I still can't figure how I can use it.

Thank you.


回答1:


For a named datatype, you probably need to bind your parameter specifying the SQLT_NTY type:

    $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();

See the manual of oci_bind_by_name for details.


For plain PL/SQL records, you're probably out of luck: according to Oracle's documentation you can't use OCI to fetch a record. As of Oracle 11g:

The following two types are internal to PL/SQL and cannot be returned as values by OCI:

  • Boolean, SQLT_BOL
  • Record, SQLT_REC

If this is correct (I'm not a regular PHP user), you will probably have to wrap your function at PL/SQ level:

  • either, in a procedure with the required number of OUT parameters;
  • or maybe, depending your needs, in a table function.

For sake of completeness, please note that Oracle 12c + OCI8 2.0.7 remove the restriction that had previously not allowed to return a boolean value.




回答2:


Thank you for you answer, I tried SQLT_NTY but it doesn't work probably because OCI can't return records like you said, ... I'll try to look at a table function.

Edit : I finally used a 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;

/

and this php function :

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;
}


来源:https://stackoverflow.com/questions/27525948/handle-a-pl-sql-function-returning-a-record-in-php

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!