目录:
一、案例
二、思索过程
三、解决方案
四、后记
正文
一、案例:
在userA用户下书写存储过程如下:
create or replace procedure sp_test is v_str1 varchar2(1000); begin v_str1 := 'ALTER TABLE userB.tb_user_info_m truncate PARTITION P201311'; execute immediate(v_str1); end sp_test;
然后在plsql中测试,结果ORACLE非常无情地报
ORA-01031:权限不足。
临近春节,怕数据空间爆满,想删数据,oracle真的很不给面子。
所以我要征服它~~~~
二、思索过程
1. 将关键部位拷贝出来,直接在userA用户下运行,完全没有异常(本例中Sqlplus和plsql中运行结果非常一致,因此和运行环境没有关系,下同):
SQL> ALTER TABLE userB.tb_user_info_m truncate PARTITION P201311;
2. 第一个步骤说明用户userA用户权限是没有问题的。
3. 在存储过程中将v_str1更改为select语句,结果也是报错,不过不是权限不足,是“ora-00942表或视图不存在”,说明在存储过程中无法查询其他用户的表:
v_str1 := 'select count(1) into v_integer from userB.tb_user_info_m';
4. 使用其他用户userC建立存储过程(这个用户一直是用来建立表分区用的,所以肯定是可以通过的)。结果确实通过了:
create or replace procedure userC.sp_test is v_str1 varchar2(1000); begin v_str1 := 'ALTER TABLE userB.tb_user_info_m truncate PARTITION P201311'; execute immediate(v_str1); end sp_test;
begin sp_test; end;
“已完成,耗时1.294秒”
5. 第4步说明存储过程写法是没有错的。问题还是出在权限上。
6. 对比userA和userC两个用户的权限,一个个权限赋予userA,发现结果运行到:grant select any table to userA; 第3步中的select语句运行通过了;
继续赋权:grant drop ant table to userA; 的时候案例中的存储过程运行通过。
7. 第6步说明问题还是出在权限上面。但是直接运行又没有问题,研究具体的副权语句,发现userA是通过权限组获得select any table 和 drop any table 权限的,而userC是直接在sys用户下运行赋any 权的语句的。因此,猜测问题是出在权限继承的问题上。
8. 新建userD,使用权限组赋权:grant role_group to userD; 同样是报“ora-00942” 和“ORA-01031” 的。去掉权限后直接赋权:grant drop ant table to userA; 存储过程执行完毕。
9. 思考结束。
三、解决方案如下:
使用sys用户直接赋权(select、insert、update、delete、alter、drop),而不要用权限组的方式赋权。因为存储过程中无法继承非直接赋予的权限。
四、后记:
其实alter权限我一开始也是单独赋予了,但是却还是报权限不足,无论是truncate还是drop表分区。
留意字眼,不是alter表而已,而是alter的时候对表分区进行操作,因此truncate和drop的权限都要赋予,不然是无法操作的。
走了很多弯路,最后幸好有个前面的例子在,才解决了。
网上说的很多都是没有作用的,诸如什么:“在目标用户下使用grant语句”等等,确实,是能够达到效果的,但是我要赋权几千个表,而且后续还有新加入的表,全部都需要手动进行赋权,都苦逼啊。直接在sys下进行any table的赋权,能省去不少功夫。
plus:如果sys没有给予对应用户with admin option的权限的话,是没有办法在userB等非sys用户使用any table 选项的。
后记全部是废话,不看也罢。