可以"类型表"在PL / SQL中操作?

时间:2017-01-20 14:36:03

标签: oracle plsql types

我有像这样定义的对象类型表

create type user_role_ty as object (
    username           varchar2(32),
    role_nam           varchar2(32)
);
create type user_role_nt as table of user_role_ty
/

并在函数中输出变量

p_user_role_list  out    bt_ww_user_role_nt

填写

select user_role_ty (username, role_nam)
    bulk collect into p_user_role_list
(...)

如何修改表格类型的变量?我想删除一些行,例如主管理员可能会看到所有,本地管理员不会看到主管理员,用户可能只看到自己等。缩短:

if is_vendor( ... ) then
    NULL;
elsif is_admin( ... ) then
    delete from p_user_role_list
    where username in ( (...) user_name_list );
else
    delete from p_user_role_list
    where username <> p_username;

根本不起作用。有几种可能性,其中没有一种是直截了当的:

  • 使用复制粘贴相同的原始选择几次轻微的条件修改使用。工作,但可怕(加上未来的风险进入错误)。
  • 使用我真正讨厌的execute immediate - PL / SQL非常适合集成脚本语言和SQL(例如语法高亮)。 execute immediate降低了PL / SQL,以便用任何语言的字符串调用SQL(与缺少许多功能的那些相比)。
  • 使用临时表,然后将内容复制到表类型变量。这是多余的不使用代码垃圾(代码应该是可读的并且有意义)。

还有其他办法吗?

3 个答案:

答案 0 :(得分:2)

我会过滤提供数据的选择查询,例如:

select user_role_ty (username, role_nam)
    bulk collect into p_user_role_list
from   user_role_table
where  case when is_vendor(...) = 'Y' then role_nam
            when is_admin(...) = 'Y' and role_nam in (<list of roles that the is_admin user is allowed to see>)
                 then role_nam
       end = role_nam
or     username = p_username;

答案 1 :(得分:2)

之前的建议很明显(在SQL中尽可能多地完成工作,或者更深入地了解#34;并设置虚拟专用数据库角色)。但是,如果您确实碰巧(或需要)坚持使用以PL / SQL为中心的解决方案,请记住,一旦您将批量收集到该集合中,它就是PL / SQL变量。

所以我不会考虑使用EXECUTE IMMEDIATE或临时表,而是编写PL / SQL逻辑来应用你拥有的任何复杂规则。

DECLARE
   p_user_role_list   user_role_ty;
BEGIN
   SELECT user_role_ty (username, role_nam)
     BULK COLLECT INTO p_user_role_list
     FROM (SELECT 'steven' username, 'admin' role_nam FROM DUAL);

   FOR indx IN 1 .. p_user_role_list.COUNT
   LOOP
      /* Apply changes like .DELETE to remove an element
         or even copy the elements you want to keep to
         a new collection */
      NULL;
   END LOOP;
END;
/

PS - 如果你真的不需要,我可以理解讨厌使用EXECUTE IMMEDIATE,但是当你确实需要执行动态SQL时,它确实提供了一种很好的,简单的本地方式来完成工作!

答案 2 :(得分:1)

正确的解决方案是将VPD策略应用于基础表(隐藏在(...)中的位。这样,PL / SQL集合只能填充用户可以看到的数据。< / p>

细粒度的访问控制非常强大。此外,被烘焙到Oracle中,比我们的手动代码更可靠。 Find out more