PL/SQL - 找不到我的局部变量

Vae*_*hin 0 sql oracle plsql oracle11g

我现在很困惑; 我正在编写一个脚本来查找用户正在进行的所有角色.这是一项正在进行中的工作,由于我对PLSQL缺乏了解,如果你知道我的意思,那么进展并不是很多.

-- Declaration of Table Type
create or replace TYPE TEST 
AS TABLE OF VARCHAR(30);

-- Function here
create or replace FUNCTION FINDPARENTS 
(
  ROLENAME IN VARCHAR2 
) 
    RETURN TEST 
    IS
    tt_t TEST;

BEGIN
    DECLARE
        results test;
        toadd test := TEST(ROLENAME);
        counter number;
        elements number:=1;
    BEGIN
        SELECT GRANTED_ROLE 
        BULK COLLECT INTO toadd 
        FROM DBA_ROLE_PRIVS 
        WHERE GRANTEE = rolename; 

        SELECT COUNT(*) 
        INTO ELEMENTS 
        FROM toadd; -- Error here.
    --(for i in 0 .. ELEMENTS) SELECT FINDPARENTS(ROLE_NAME) FROM DUAL UNION RESULT ... or something.
    END;
END;
Run Code Online (Sandbox Code Playgroud)

此代码导致"表或视图未找到"错误,因为在第二行中无法找到"toadd"(选择计数(*)...),尽管可以在上面的语句中找到(选择GRANTED_ROLE .. .) 这怎么可能呢 ?

另外,实现递归的最佳方法是什么?我的函数返回一个VARCHAR表,如何让它"解析"每个role_names,直到角色不再具有父角色?

APC*_*APC 5

toadd是一个变量.我们不能在FROM子句中使用那些,只能使用表.但是,因为它被声明为嵌套表类型,我们可以将它转换为具有table()函数的表:

 SELECT COUNT(*) 
    INTO ELEMENTS 
    FROM table(toadd); 
Run Code Online (Sandbox Code Playgroud)

为了回答问题的其他部分,Oracle有一些简洁的层次结构语法.了解更多.

因此,您可以获得所有直接或间接授予的角色的列表,如下所示:

select granted_role
bulk collect into tt_t
from dba_role_privs 
connect by granted_role = prior grantee
start with granted_role = 'ROOT'
/
Run Code Online (Sandbox Code Playgroud)

填充集合时使用BULK COLLECT语法.

  • 像往常一样,APC给出了很好的建议.关于BULK COLLECT的一个小附录:对于相对较小的数据集,选择批量收集到配方中是完全正确的.但是如果你使用大量的行,你可能会消耗太多的PGA内存.因此最好使用显式游标,然后使用带有LIMIT子句的带有fetch-bulk collect的简单循环.这是一个带有示例的LiveSQL脚本:https://livesql.oracle.com/apex/livesql/file/content_DUT0KQ710EOQ5DO5TAVYUU904.html (2认同)