VPD这东西,ORACLE8i就已经有了,以前我们的系统主要是面向医院使用,更多的是一个OLTP 系统,虽然VPD有用,但不值得冒这个险使用这个技术。但如果使用在一个汇总的数据库中,尤其对于安全特性考虑比较多的地方,还是值得试一试。
前段时间开发了一个科训系统,本意是给科训局做统计上报。这个程序能否推下去,目前还不明朗,但可以拿其中的数据做些测试。
以论文(表paper)为例(个人认为,这个表的名称应该为复数更合适),其中有个字段organ_code 表示该论文属于哪个单位的,单位编码是按级别编写,例如第二军医大学为D2, 长征医院为D22 ,如果不同单位的人想访问这个表,则希望只能访问其本单位或者下属单位的数据。
表users 中有个字段organ_code 表示该用户属于哪个单位。
以SYSTEM用户创建包:pck_vpd
create or replace package pck_vpd
as
p_organ_code users.organ_code%type;
procedure set_organ_code(v_organ_code users.organ_code%type);
function predicate (obj_schema varchar2, obj_name varchar2) return varchar2;
end pck_vpd;
/
create or replace package body pck_vpd as
procedure set_organ_code(v_organ_code users.organ_code%type) is
begin
p_organ_code := v_organ_code;
end set_organ_code;
function predicate (obj_schema varchar2, obj_name varchar2) return varchar2 is
begin
return 'organ_code like ''' || p_organ_code||'%''';
end predicate;
end pck_vpd;
/
创建触发器:
create or replace trigger trg_vpd
after logon on database
declare
v_organ_code users.organ_code%type;
begin
begin
select organ_code into v_organ_code
from users where upper(db_user) = user;
exception when NO_DATA_FOUND then
v_organ_code :='';
end;
pck_vpd.set_organ_code(v_organ_code);
end;
/
添加策略:
begin
dbms_rls.add_policy (
'TRAIN',
'PAPER',
'paper policy name',
user,
'pck_vpd.predicate',
'select,update,delete');
end;
/
以用户LGB(我们一个同事的用户名,我们称之为老干部)为例:
update users set organ_code='E' where db_user='LGB';
commit;
SQL> conn lgb/lgb@dbserver
Connected.
SQL> select distinct organ_code from paper ;
ORGAN_COD
---------
E
E0845
修改下用户的organ_code
update users set organ_code='D' where db_user='LGB';
commit;
SQL> conn lgb/lgb@dbserver
Connected.
SQL> select distinct organ_code from paper ;
ORGAN_COD
---------
D
D30
D31
D40
D4061
D4062
D41
D45
8 rows selected.
我们在很多例子里都看到要创建触发器,其实主要是对于那些非静态的谓词创建,如果是静态的,例如 ” dept_no = 20 “ 当然无需触发器。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/9036/viewspace-521065/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/9036/viewspace-521065/