将PHP数组传递给Oracle存储过程(PLS-00306:错误数量或参数类型)

时间:2014-08-14 14:44:43

标签: php sql arrays oracle oracle11g

使用PHP 5.3.2和Oracle 11G,我试图将数组从PHP传递到oracle存储过程。这是我的PL / SQL:

create or replace type NUM_ARRAY as table of number;

create or replace package txa as  

  procedure upsert_txa_compliance_slct( v_compl_id_array  in num_array);

end txa; 

create or replace package body txa as

    procedure upsert_txa_compliance_slct(v_compl_id_array  in num_array)
    is
    begin
        .
        . -- sql code removed for brevity.  package and body compile no errors
        .
    end upsert_txa_compliance_slct;

end;

查询:

  $sql = "begin txa.upsert_txa_compliance_slct(:my_array); end;";

PHP代码我试图绑定数组并执行:

首先:

<?

$this->conn = ociplogon($dbuser, $dbpass, $dbname);
$this->commit_mode = OCI_COMMIT_ON_SUCCESS;
$this->sth = @ociparse($this->conn, $sql);

oci_bind_array_by_name($this->sth, 
                       ':my_array', 
                       $my_array, 
                       count($my_array), 
                       -1, 
                       SQLT_CHR);

$r = @ociexecute($this->sth, $this->commit_mode);

?>

会产生此错误:

PLS-00306:拨打&#39; UPSERT_TXA_COMPLIANCE_SLCT&#39;

的参数数量或参数类型错误

我明显过了1个arg。那么,我有什么问题/如何修复类型问题?

另外我发现了这个

http://www.oracle.com/technetwork/articles/seliverstov-multirows-098120.html

并尝试使用oci集合的旧方式:

 $collection = oci_new_collection($this->conn,"NUM_ARRAY");

将我的oracle类型更改为:

create or replace type NUM_ARRAY as varray(100) of number;

我收到了这个错误:

oci_new_collection():ORA-22318:输入类型不是数组类型

任何帮助都会非常感激。

编辑2014年8月14日下午7:08

我更改了我的php oci_bind函数调用以使用SQLT_NUM作为类型。这没有任何影响。然后我改变了我的包裹:

type num_array is table of number index by binary_integer;

(我也从我的架构中删除了原来的num_array)

这个改变使我可以将我的数组传递给存储过程,但是我不能像这样使用数组作为嵌套表:

delete 
  from my_table
 where id not in (select column_value from table(v_compl_id_array));

当我尝试使用该语句编译包体时,我收到此错误:

PL/SQL: ORA-22905: cannot access rows from a non-nested table item

所有文档都告诉我返回架构级别类型?但是当我这样做时,我得到了另一个错误。我知道我可以通过我的pl / sql数组上的循环找到另一种方法来做到这一点,但我真的很想能够使用该模式级别类型。

1 个答案:

答案 0 :(得分:3)

答案是这样的。您不能将全局创建或模式级别类型用作存储过程的参数。 PHP的oci_bind_array_by_name似乎不适用于全局创建的类型,但是您需要全局创建的类型才能将您的数组用作子选择中的嵌套表。所以....这就是我如何使用它。我很高兴听到其他解决方案!但就目前而言,这就是我所做的。

-- globally create a type table of number

create or replace type num_array is table of number;

-- in my package i created an internal type table of number

type i_num_array is table of number index by binary_integer;

-- i then used i_num_array (internal type) as the type for my IN parameter to the procedure

upsert_TXA_compliance_slct( v_compl_id_array  in i_num_array)

-- in my procedure i also created a variable that is the type of my globally created type

v_num_array num_array := num_array();

-- then i populated that variable in a loop inside my procedure with the values in my IN param

for i in 1 .. v_compl_id_array.count
loop
  v_num_array.extend(1);
  v_num_array(i) := v_compl_id_array(i);
end loop; 

-- then i used v_num_array as my nested table so this now works:

delete from my_table where id in (select * from table(v_num_array));