如何从 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 过程的主要内容,如果未能解决你的问题,请参考以下文章