我有像这样定义的对象类型表
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(与缺少许多功能的那些相比)。还有其他办法吗?
答案 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。