如何在update语句的where子句中使用数组类型

时间:2018-04-30 07:37:25

标签: oracle plsql oracle9i

我希望程序获取禁用权限列表,并在表中更新其记录。为了完成这个场景,我使用下面的代码将数组定义为数据库对象:

CREATE OR REPLACE TYPE T_DISABLE_LIST IS TABLE OF NUMBER(32)

然后我在过程签名中定义了一个输入参数,并得到了传递值。

PROCEDURE PRC_ROLE_PRIVILAGE_MANAGEMENT(P_REQ_USER_ID    IN VARCHAR2,
                                        P_DISABLE_LIST   IN T_DISABLE_LIST,
                                        P_RES_DESC       OUT VARCHAR2)
BEGIN
    UPDATE T_ PRIVILAGE p
       SET P.ENABLE_STATUS = 0, P.GRANT_USERID = P_REQ_USER_ID
    WHERE P.ID IN (SELECT * FROM TABLE(P_DISABLE_LIST));

    COMMIT;
EXCEPTION
    WHEN OTHERS THEN
        RES_DESC := SUBSTR(SQLERRM,1, 400);
END;

此过程将成功编译。但是当我测试它时,我收到了这个错误:

  

ORA-22905:无法访问非嵌套表项的行

任何人都可以帮助我吗?并说明为什么这段代码无法正常工作?

最后,我该如何解决这个问题?

P.S:我的orcale版本是9.2 !!!

1 个答案:

答案 0 :(得分:2)

这假设您使用的是Oracle 10g或更高版本(并且是在OP澄清他们使用的版本之前编写的)

使用MEMBER OF运算符:

UPDATE T_PRIVILAGE
SET    ENABLE_STATUS = 0,
       GRANT_USERID  = P_REQ_USER_ID
WHERE  ID MEMBER OF P_DISABLE_LIST;

您还可以使用COLUMN_VALUE伪列:

UPDATE T_PRIVILAGE
SET    ENABLE_STATUS = 0,
       GRANT_USERID  = P_REQ_USER_ID
WHERE  ID IN ( SELECT COLUMN_VALUE FROM TABLE( P_DISABLE_LIST ) );
  

为什么此代码无法正常工作?

SELECT * FROM TABLE( P_DISABLE_LIST )

从表中选择行。但是,该表由表集合表达式生成,并且没有底层数据库表来引用一行,因此Oracle生成ORA-22905异常。(如果集合存储在嵌套表中,则会有一个基础表;这就是为什么在例外中特别提到这种情况的原因。

更新:PL / SQL解决方案:

FOR i IN 1 .. P_DISABLE_LIST.COUNT LOOP
  UPDATE T_PRIVILAGE
  SET    ENABLE_STATUS = 0,
         GRANT_USERID  = P_REQ_USER_ID
  WHERE  ID = P_DISABLE_LIST(i);
END LOOP;