如何使用数组参数创建 oracle 存储过程

Posted

技术标签:

【中文标题】如何使用数组参数创建 oracle 存储过程【英文标题】:How to create an oracle stored procedure with an array parameter 【发布时间】:2016-02-15 21:04:27 【问题描述】:

我在一个包中创建了一个 Oracle 存储过程。我确实喜欢这样:

CREATE OR REPLACE PACKAGE PACKFACE IS
TYPE LIST_IDS IS TABLE OF INT INDEX BY BINARY_INTEGER;
PROCEDURE P_SELECT_IDBFRIENDS (CONSULTA OUT SYS_REFCURSOR,COD_US IN INT,IDS_NOT IN LIST_IDS);
END;

包的主体是:

CREATE OR REPLACE PACKAGE BODY PACKFACE IS
    PROCEDURE P_SELECT_IDBFRIENDS (CONSULTA OUT SYS_REFCURSOR,COD_US IN INT, IDS_NOT IN LIST_IDS) IS
    BEGIN
        OPEN CONSULTA FOR 
        SELECT ID_US1,ID_US2 FROM T_FRIENDSHIP WHERE ID_US1=COD_US AND ID_US2 NOT IN (SELECT COLUMN_VALUE FROM TABLE(IDS_NOT));
    END;
END;
/

这些在我的 Oracle 12c 服务器中没问题,但我在 Oracle 11g 中执行相同的代码时出现错误,无法访问非嵌套表项中的行。解决方案是什么?提前致谢 修复此问题后。似乎另一个我的 Python 代码被破坏了。我有这个程序:

def select_ids(self,cod_us,ids_not):
    lista = []
    try:
        cursor = self.__cursor.var(cx_Oracle.CURSOR)
        varray = self.__cursor.arrayvar(cx_Oracle.NUMBER,ids_not)
        l_query = self.__cursor.callproc("PROC_SELECT_IDS_ENT_AMISTADES", [cursor, cod_us, varray])
        lista = l_query[0]
        return lista
    except cx_Oracle.DatabaseError as ex:
        error, = ex.args
        print(error.message)
        return lista

PLS-00306 调用过程时参数的数量或类型错误。使用 Oracle 12c 没问题。再次提前感谢。

【问题讨论】:

我相信您需要在 SQL 中定义您的集合类型。是否有理由需要关联数组(只能在 PL/SQL 中定义)而不是嵌套表(可以在 SQL 和 PL/SQL 中定义)? 我正在寻找相同错误的解决方案 首先我必须排除存储在数组中的 id,然后我使用 in 子句排除 id(可变大小)进行选择 【参考方案1】:

您不能在 Oracle 11 的 SQL 查询中使用 PL/SQL 中定义的集合类型。

如果你想在 SQL 和 PL/SQL 中使用一个集合,那么你必须在 SQL 中定义它:

CREATE TYPE LIST_IDS IS TABLE OF INT;

那么你可以这样做:

CREATE OR REPLACE PACKAGE PACKFACE IS
  PROCEDURE P_SELECT_IDBFRIENDS (
    CONSULTA OUT SYS_REFCURSOR,
    COD_US IN INT,
    IDS_NOT IN LIST_IDS
  );
END;
/
SHOW ERRORS;

CREATE OR REPLACE PACKAGE BODY PACKFACE IS
  PROCEDURE P_SELECT_IDBFRIENDS (
    CONSULTA OUT SYS_REFCURSOR,
    COD_US IN INT,
    IDS_NOT IN LIST_IDS
  )
  IS
  BEGIN
    OPEN CONSULTA FOR 
    SELECT ID_US1,ID_US2
    FROM   T_FRIENDSHIP
    WHERE  ID_US1=COD_US
    AND    ID_US2 NOT MEMBER OF IDS_NOT;
  END;
END;
/
SHOW ERRORS;

【讨论】:

非常感谢,已修复。现在问题出在我的python代码中。我会修改我的问题【参考方案2】:

首先你应该像这样创建一个 oracle 类型:

CREATE OR REPLACE TYPE LIST_IDS AS TABLE OF INT;

然后,您应该使用过程和嵌套表在参数中创建包,如下所示:

CREATE OR REPLACE PACKAGE PACKFACE IS
TYPE LISTADO_IDS IS TABLE OF INT INDEX BY PLS_INTEGER;
PROCEDURE P_SELECT_IDBFRIENDS (CONSULTA OUT SYS_REFCURSOR,COD_US IN INT,IDS_NOT IN LISTADO_IDS);
END;

最后你应该创建身体。您将数据从 oracle 类型传递给嵌套表,如下所示:

CREATE OR REPLACE PACKAGE BODY PACKFACE IS
    PROCEDURE P_SELECT_IDBFRIENDS (CONSULTA OUT SYS_REFCURSOR,COD_US IN INT, IDS_NOT IN LISTADO_IDS) 
    IS
        num_array FACEBOOK.LIST_IDS;
    BEGIN
        num_array:=LIST_IDS();
        for i in 1 .. IDS_NOT.count
        loop
            num_array.extend(1);
            num_array(i) := IDS_NOT(i);
        end loop; 
        OPEN CONSULTA FOR 
        SELECT ID_US1,ID_US2 FROM T_FRIENDSHIP WHERE ID_US1=COD_US AND ID_US2 NOT IN (SELECT COLUMN_VALUE FROM TABLE(num_array));
    END;
END;

我这样做了,我得到了解决 python 错误错误数字或类型参数的方法。祝你好运。

【讨论】:

以上是关于如何使用数组参数创建 oracle 存储过程的主要内容,如果未能解决你的问题,请参考以下文章

Oracle PL/SQL:如何使用可变数组作为输出参数执行过程?

oracle存储过程传入一个字符串参数'1,2,3,4,5,6,7,8',如何分割并转为数字?

如何创建带参数的 Oracle 存储过程?

oracle存储过程中循环for in是如何使用的

在oracle中创建带参存储过程,传进去的参数可以为空么?在存储过程中要如何判断传进来的值是不是为空。

SQL Server2008 存储过程传入表名称和列名称,如何在语句中使用表明引用列名?