Обработка функции PL/SQL, возвращающей запись в PHP

Я искал в Интернете, и я не нашел ответа, так что я здесь.

У меня есть функция 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 

Так что это самоочевидная ошибка, но я до сих пор не могу понять, как я могу ее использовать.

Спасибо.

2 ответа

Решение

Для именованного типа данных вам, вероятно, нужно связать свой параметр, указав 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, вы не можете использовать OCI для извлечения записи. Начиная с Oracle 11g:

Следующие два типа являются внутренними для PL/SQL и не могут быть возвращены в качестве значений OCI:

  • Boolean, SQLT_BOL
  • Запись, SQLT_REC

Если это правильно (я не обычный пользователь PHP), вам, вероятно, придется обернуть свою функцию на уровне PL / SQ:

  • либо в процедуре с необходимым количеством OUT параметры;
  • или, может быть, в зависимости от ваших потребностей, в табличной функции.

Для полноты картины обратите внимание, что Oracle 12c + OCI8 2.0.7 убирает ограничение, которое ранее не позволяло возвращать логическое значение.

Спасибо за ваш ответ, я пробовал SQLT_NTY, но он, вероятно, не работает, потому что OCI не может возвращать записи, как вы сказали... Я попробую взглянуть на табличную функцию.

Изменить: я, наконец, использовал ПРОЦЕДУРУ

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;
}
Другие вопросы по тегам