【问题标题】:Execute Immediate fails even with CREATE table grant即使有 CREATE 表授权,立即执行也会失败
【发布时间】:2016-02-19 19:31:48
【问题描述】:

我在使用存储过程中的立即执行命令创建表时遇到问题。但是我得到“权限不足”的错误。我检查了其他线程并确保用户已授予它“CREATE TABLE”权限。但是我仍然看到同样的错误。

SQL> select * from USER_SYS_PRIVS;

USERNAME                       PRIVILEGE                                ADM
------------------------------ ---------------------------------------- ---
MYUSER            CREATE VIEW                              NO
MYUSER            UNLIMITED TABLESPACE                     NO

SQL> select * from session_privs;

PRIVILEGE
----------------------------------------
CREATE SESSION
UNLIMITED TABLESPACE
CREATE TABLE
CREATE CLUSTER
CREATE VIEW
CREATE SEQUENCE
CREATE PROCEDURE
CREATE TRIGGER
CREATE TYPE
CREATE OPERATOR
CREATE INDEXTYPE

11 rows selected.

我创建的 Dummy 程序是:

create or replace procedure sp_dummy
   as
   begin
      execute immediate 'Create table Dummy99_99 (Dummy_Field number)';
   end sp_dummy;
   /

详细错误:

ERROR at line 1:
ORA-01031: insufficient privileges
ORA-06512: at "MYUSER.SP_DUMMY", line 4
ORA-06512: at line 1

我做错了什么吗?

【问题讨论】:

  • 请注意,PL/SQL 过程默认使用定义者的权限,即它以编译该过程的用户的权限运行,而不是以运行/调用该过程的用户的权限运行。这可能与您的情况相关,也可能不相关。
  • 此错误与“CREATE TABLE”权限无关,因为 CREATE TABLE Priv 只会在运行时执行。这与 CREATE PROCEDURE 权限有关。尝试 GRANT CREATE PROCEDUTE T​​O MYUSER;并再次测试。让我知道这是否有帮助
  • @AvrajitRoy - 错误来自程序的执行,而不是它的创建 - 尽管问题中没有明确说明。错误堆栈具有来自代码块的 PL/SQL 错误。如果create procedure priv 丢失(实际上没有,您可以在session_privs 中看到它),您只需从create procedure 获取 ORA-01031,而没有 ORA-06512 跟踪。
  • yupps 错过了那个痕迹:P。在这种情况下,它应该运行良好,因为存在 CREATE TABLE Priv。仅当尝试在另一个模式中创建表时才会发生这种情况。在这种情况下,CREATE ANY TABLE priv 必须这样做。
  • @AvrajitRoy - 但它并没有尝试在另一个模式中创建表;这是因为权限是通过角色授予的。

标签: oracle plsql oracle11g grant execute-immediate


【解决方案1】:

如果你以myuser用户连接,你应该可以创建过程,并执行它来创建表。

完成该任务所需的唯一权限是:

  • 创建会话
  • 创建表
  • 创建过程

然后连接到用户后执行程序:

SQL> CREATE USER TEST IDENTIFIED BY TEST;

User created.

SQL> GRANT CREATE SESSION, CREATE TABLE, CREATE PROCEDURE TO TEST;

Grant succeeded.

SQL> conn TEST/TEST@pdborcl;
Connected.
SQL> show user
USER is "TEST"
SQL> CREATE OR REPLACE PROCEDURE sp_dummy
  2  AS
  3  BEGIN
  4    EXECUTE immediate 'Create table Dummy99_99 (Dummy_Field number)';
  5  END sp_dummy;
  6  /

Procedure created.

SQL> EXEC sp_dummy;

PL/SQL procedure successfully completed.

SQL> select * from dummy99_99;

no rows selected

【讨论】:

    【解决方案2】:

    您只有 create view 直接授予您的用户。您可以看到的其他系统权限来自角色和roles are disabled in definer's-rights stored procedures。查看user_role_privs 以查看您已被授予的角色,您可以在role_sys_privs 中查看每个角色为您提供的权限(以角色名称作为被授予者)。也可能有多层角色。

    如果您在尝试静态创建表之前执行set role none,您会看到相同的错误。最少设置的演示:

    create role myrole;
    grant create session, create table, create procedure to myrole;
    create user myuser identified by mypasswd;
    grant myrole to myuser;
    grant create view, unlimited tablespace to myuser;
    

    然后作为那个用户:

    SQL> connect myuser/mypasswd
    Connected.
    SQL> select * from user_sys_privs;
    
    USERNAME                       PRIVILEGE                                ADM
    ------------------------------ ---------------------------------------- ---
    MYUSER                         UNLIMITED TABLESPACE                     NO
    MYUSER                         CREATE VIEW                              NO
    
    2 rows selected.
    
    SQL> select * from session_privs;
    
    PRIVILEGE
    ----------------------------------------
    CREATE SESSION
    UNLIMITED TABLESPACE
    CREATE TABLE
    CREATE VIEW
    CREATE PROCEDURE
    
    5 rows selected.
    
    SQL> Create table Dummy99_99 (Dummy_Field number);
    
    Table created.
    
    SQL> drop table Dummy99_99 purge;
    
    Table dropped.
    
    SQL> set role none;
    
    Role set.
    
    SQL> Create table Dummy99_99 (Dummy_Field number);
    Create table Dummy99_99 (Dummy_Field number)
    *
    ERROR at line 1:
    ORA-01031: insufficient privileges
    

    还有你的存储过程版本:

    SQL> connect myuser/mypasswd
    Connected.
    SQL> create or replace procedure sp_dummy
      2  as
      3  begin
      4    execute immediate 'Create table Dummy99_99 (Dummy_Field number)';
      5  end sp_dummy;
      6  /
    
    Procedure created.
    
    SQL> exec sp_dummy;
    BEGIN sp_dummy; END;
    
    *
    ERROR at line 1:
    ORA-01031: insufficient privileges
    ORA-06512: at "MYUSER.SP_DUMMY", line 4
    ORA-06512: at line 1
    

    为了能够从存储过程动态创建表,您的 DBA 需要将create table 直接授予您的用户:

    grant create table to myuser;
    

    然后再次尝试该过程:

    SQL> connect myuser/mypasswd
    Connected.
    SQL> select * from user_sys_privs;
    
    USERNAME                       PRIVILEGE                                ADM
    ------------------------------ ---------------------------------------- ---
    MYUSER                         UNLIMITED TABLESPACE                     NO
    MYUSER                         CREATE TABLE                             NO
    MYUSER                         CREATE VIEW                              NO
    
    SQL> exec sp_dummy;
    
    PL/SQL procedure successfully completed.
    
    SQL> desc Dummy99_99
     Name                                      Null?    Type
     ----------------------------------------- -------- ----------------------------
     DUMMY_FIELD                                        NUMBER
    

    请注意,user_sys_privs 现在显示 create table 已被直接授予,这在之前或问题中都没有。

    但是,您不太可能真正想要动态创建对象,因为架构应该定义明确且稳定 - 这种类型的更改应该受到控制并成为发布过程的一部分。但作为练习,您需要直接授权。

    【讨论】:

      【解决方案3】:

      当使用立即执行时,过程必须明确告诉 oracle 它必须以特定用户的权限运行。

      AUTHID CURRENT_USER,使用运行程序的用户的权限。 AUTHID DEFINER,使用过程所有者的权限。

      这是在创建过程时使用 AUTHID 选项完成的。

      CREATE OR REPLACE PROCEDURE PROC_NAME AUTHID CURRENT_USER
      IS
      .....
      

      我遇到了类似的问题,并从以下方面得到了理解: Execute Immediate within a stored procedure keeps giving insufficient priviliges error

      【讨论】:

        【解决方案4】:

        必要的让步如下:

        GRANT CREATE TABLE TO "USER";
        GRANT EXECUTE ANY PROCEDURE TO "USER" ;
        

        【讨论】:

        • 欢迎来到 Stack Overflow!虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。也请尽量不要用解释性的 cmets 挤满你的代码,因为这会降低代码和解释的可读性!
        猜你喜欢
        • 1970-01-01
        • 2018-12-23
        • 1970-01-01
        • 2016-02-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多