如何从 PHP 代码调用复杂的 Oracle 过程

Posted

技术标签:

【中文标题】如何从 PHP 代码调用复杂的 Oracle 过程【英文标题】:How to call a complex Oracle Procedure from PHP Code 【发布时间】:2021-06-14 03:33:02 【问题描述】:

请帮我解决以下问题。

简介: 我制作了一个自定义 MVC 框架,在其中制作了一个名为“Oracle 存储过程”的方法。所以现在我可以与 php-OCI 模块建立连接,可以获取和插入记录,还可以调用一个简单的 hello-world 程序。但是我有一个包含 In 和 Out 参数的长过程,但我无法调用该过程。

问题: 当我在 SQL 编辑器中直接调用该过程并运行它时,它就可以工作了。但是当我从 PHP 调用时,它给了我一个错误。

    我从 SQL 编辑器调用该过程,如下所示:
DECLARE
    V_HOSPITAL_CODE VARCHAR2(200);
    V_SPECIALTY_ID  NUMBER;
    V_refcur SYS_REFCURSOR;
    lsn1 NUMBER;
    lsn2 VARCHAR2(200);
    lsn3 VARCHAR2(200);

BEGIN
    V_HOSPITAL_CODE := 'ABC';
    V_SPECIALTY_ID  := 1;
    SP_DOCTORS_LIST( V_HOSPITAL_CODE => V_HOSPITAL_CODE, V_SPECIALTY_ID => V_SPECIALTY_ID, V_REFCUR => V_refcur );
    loop
        FETCH V_refcur into lsn1,lsn2,lsn3; 
        exit when V_refcur%notfound;
        DBMS_OUTPUT.PUT_LINE(lsn1 || ' | ' || lsn2 || ' | ' || lsn3);
    end loop;
    CLOSE V_REFCUR;
END;

注意:以上程序运行成功

    调用过程的 PHP 代码:
        $sql = 'BEGIN SP_PATIENT_DATA(:V_HOSPITAL_CODE, :V_PATIENTID, :V_REFCUR); END;';
        $stmt = oci_parse($this->conn, $sql);
        // Assign a value to the input
        $V_HOSPITAL_CODE = 'ABC';
        $V_PATIENTID = 24;
        oci_bind_by_name($stmt, ':V_HOSPITAL_CODE', $V_HOSPITAL_CODE);
        oci_bind_by_name($stmt, ':V_PATIENTID', $V_PATIENTID);
        oci_bind_by_name($stmt, ':V_REFCUR', $V_REFCUR);
        oci_execute($stmt);
        print "$V_REFCUR\n";

上面的代码给了我下面的错误

Warning: oci_execute(): ORA-06550: line 1, column 7: PLS-00306: wrong number or types of arguments in call to 'SP_PATIENT_DATA' ORA-06550: line 1, column 7: PL/SQL: Statement ignored in /var/www/html/project/app/Components/Connection.php on line 72

PHP:7.4 操作系统:Ubuntu 20 甲骨文:11g

感谢和问候 坦玛亚

【问题讨论】:

【参考方案1】:

将您的 REF CURSOR 绑定更改为类似

$V_REFCUR = oci_new_cursor($conn);
oci_bind_by_name($stmt, ':V_REFCUR', $V_REFCUR, -1, OCI_B_CURSOR);

有关示例,请参阅 PHP OCI8 文档https://www.php.net/manual/en/function.oci-new-cursor.php。

另一个例子是:

<?php

/*

  Example using a REF CURSOR to return query results from a stored
  procedure.

  Create this package before running this PHP script:

    create or replace
      procedure myproc(p1 out sys_refcursor) as
    begin
      open p1 for
        select last_name from employees where rownum <= 5;
    end;
    /
*/

$c = oci_connect('cj', 'cj', 'localhost/orclpdb1');

$stmtarray = array(
    "create or replace
      procedure myproc(p1 out sys_refcursor) as
    begin
      open p1 for
        select last_name from employees where rownum <= 5;
    end;"
);

foreach ($stmtarray as $stmt) 
    $s = oci_parse($c, $stmt);
    $r = oci_execute($s);
    if (!$r) 
        $m = oci_error($s);
        if ($m['code'] != 942)   // ignore table or view doesn't exist
            echo $m['message'], "\n";
        
    


// Excute the call to the PL/SQL stored procedure
$stid = oci_parse($c, "call myproc(:rc)");
$refcur = oci_new_cursor($c);
oci_bind_by_name($stid, ':rc', $refcur, -1, OCI_B_CURSOR);
oci_execute($stid);

// Execute and fetch from the cursor
oci_execute($refcur);
echo '<table border="1">';
while($row = oci_fetch_assoc($refcur)) 
  echo '<tr>';
  foreach ($row as $c) 
    echo "<td>$c</td>\n";
  
  echo '</tr>';

echo '</table>';

?>

如果 REF CURSOR 包含很多行,请不要忘记调整预取大小。

更多信息在The Underground PHP and Oracle Manual

【讨论】:

以上是关于如何从 PHP 代码调用复杂的 Oracle 过程的主要内容,如果未能解决你的问题,请参考以下文章

从 PHP 调用 Oracle 包中存在的函数/过程

如何从 PHP 代码中调用 MySQL 存储过程?

如何从 PHP 代码中调用 MySQL 存储过程?

如何从 PHP 代码中调用 MySQL 存储过程?

PHP如何调用SQLServer2012的存储过程并获取返回结果集及出参?

从另一个存储过程 oracle 调用存储过程