首页 > 解决方案 > 使用过程但不使用 plsql 块创建 Oracle 序列时获得足够的权限

问题描述

Begin
Execute immediate 'CREATE SEQUENCE seq1 MINVALUE 1 MAXVALUE 99 START WITH 1INCREMENT BY 1 CACHE 20';
End;
Sequence creating successfully.

Create or replace procedure proc_seq as
Begin
Execute immediate 'CREATE SEQUENCE seq2 MINVALUE 1 MAXVALUE 99 START WITH 1INCREMENT BY 1 CACHE 20';
End;

Exec proc_seq();
Error: Insufficient Privilege...

标签: oraclestored-proceduresplsqldynamic-sql

解决方案


这是一个调用者/定义者权利问题。默认情况下,存储过程具有定义者的权利(DR - 强调添加):

在服务器调用期间,当 DR 单元被推入调用堆栈时,数据库存储当前启用的角色以及 和 的当前CURRENT_USERCURRENT_SCHEMA。然后它将 CURRENT_USER 和 CURRENT_SCHEMA 都更改为 DR 单元的所有者,并仅启用角色PUBLIC

如果通过角色授予您创建序列的权限,则由于该角色将被禁用,因此该权限无效。您可以通过运行来验证情况是否如此set role none,这将导致您的匿名块失败并出现相同的错误。

正如@Littlefoot 所说,您可以将特权直接授予您,而不是(或同时)通过角色。

或者,您可以指定该过程应具有调用者的权限:

Create or replace procedure proc_seq
authid current_user
as
Begin
Execute immediate 'CREATE SEQUENCE seq2 MINVALUE 1 MAXVALUE 99 START WITH 1INCREMENT BY 1 CACHE 20';
End;
/

exec proc_seq;

PL/SQL procedure successfully completed.

select seq2.nextval from dual;

   NEXTVAL
----------
         1

希望这是一个人为的例子;无论如何,您通常不会在运行时创建数据库对象...


这种方法的警告是它可能不适合您打算如何调用该过程。如果您以自己的身份运行它,那很好,但如果您将授予其他用户执行权限,那么他们将必须拥有相关权限(直接授予或通过角色授予);并将在自己的模式中创建对象。这可能正是您想要的。但如果不是,并且您不想授予create sequence调用者或让他们创建自己的对象,那么您可以保留具有定义者权限的过程并直接将权限授予您的用户。


推荐阅读