在存储过程中执行立即持续提供权限不足错误

Posted

技术标签:

【中文标题】在存储过程中执行立即持续提供权限不足错误【英文标题】:Execute Immediate within a stored procedure keeps giving insufficient priviliges error 【发布时间】:2009-06-15 13:45:31 【问题描述】:

这里是存储过程的定义:

CREATE OR REPLACE PROCEDURE usp_dropTable(schema VARCHAR, tblToDrop VARCHAR) IS
BEGIN
  DECLARE v_cnt NUMBER;
  BEGIN
    SELECT COUNT(*) 
      INTO v_cnt 
      FROM all_tables 
     WHERE owner = schema
       AND table_name = tblToDrop;

     IF v_cnt > 0 THEN 
        EXECUTE IMMEDIATE('DROP TABLE someschema.some_table PURGE');
     END IF;
   END;
END;

来电:

CALL usp_dropTable('SOMESCHEMA', 'SOME_TABLE');

由于某种原因,我不断收到 EXECUTE IMMEDIATE 命令的权限不足错误。上网查了一下,发现权限不足的错误,一般是oracle用户账户没有权限执行查询中使用的命令passes,本例中为DROP。但是,我有删除权限。我真的很困惑,似乎找不到适合我的解决方案。

提前感谢您。

解决方案:

正如史蒂夫在下面提到的,Oracle 安全模型很奇怪,因为它需要在过程中的某个地方明确知道要使用什么样的权限。让 Oracle 知道这一点的方法是在 CREATE OR REPLACE 语句中使用 AUTHID 关键字。如果您想要与过程的创建者相同级别的权限,则使用 AUTHID DEFINER。如果希望 Oracle 使用当前运行存储过程的用户的权限,则需要使用 AUTHID CURRENT_USER。过程声明如下:

CREATE OR REPLACE PROCEDURE usp_dropTable(schema VARCHAR, tblToDrop VARCHAR) 
AUTHID CURRENT_USER IS
BEGIN
  DECLARE v_cnt NUMBER;
  BEGIN
    SELECT COUNT(*) 
      INTO v_cnt 
      FROM all_tables 
     WHERE owner = schema
       AND table_name = tblToDrop;

     IF v_cnt > 0 THEN 
        EXECUTE IMMEDIATE('DROP TABLE someschema.some_table PURGE');
     END IF;
   END;
END;

感谢大家的回复。这绝对是一个非常烦人的问题。

【问题讨论】:

我遇到了类似的问题,但有趣的是没有使用 'AUTHID DEFINER' 或 'AUTHID CURRENT_USER' 程序正在执行 drop table 语句而不是 create table。 AUTHID 解决方案有效 :) 谢谢! 谢谢,这两个词“AUTHID CURRENT_USER”解决了我的问题!谢谢! 【参考方案1】:

Oracle 的安全模型是这样的,当使用立即执行(在 PL/SQL 块或过程的上下文中)执行动态 SQL 时,用户没有通过角色成员资格授予的对象或命令的权限。您的用户可能具有“DBA”角色或类似角色。您必须明确授予该用户“删除表”权限。如果您尝试从另一个模式(例如 sys 或 system)中的表中进行选择,这同样适用 - 您需要将该表的显式 SELECT 权限授予该用户。

【讨论】:

感谢您的回复。我尝试了EXECUTE IMMEDIATE('GRANT drop table ON ' || schema_name || '.' || tblToDrop || ' TO ben');,但我收到了该行的无效特权错误。我在网上寻找为删除表分配权​​限,但我似乎找不到任何东西。我尝试了所有并“删除表”,但我得到了同样的错误。你知道我在哪里可以找到正确的特权名称或我在这里做错了什么吗?再次感谢您。 不要使用 EXECUTE IMMEDIATE 来授予权限。您需要将删除表权限授予 BEN:GRANT DROP TABLE TO BEN 史蒂夫,我刚刚想通了。原来我可以使用 AUTHID 在过程中定义权限。如果我想要与创建者相同的权限,我使用 AUTHID DEFINER。如果我想要当前用户的权限,我使用 AUTHID CURRENT_USER。下面是过程 shell 的外观: CREATE OR REPLACE PROCEDURE some_procedure AUTHID CURRENT_USER IS BEGIN DECLARE BEGIN END;结束; @SteveBroberg 在我的问题中,我拥有的所有GRANT 权限,因为我使用的是用户模式。 ***.com/questions/57070212/…【参考方案2】:

您应该将此示例与 AUTHID CURRENT_USER 一起使用:

CREATE OR REPLACE PROCEDURE Create_sequence_for_tab (VAR_TAB_NAME IN VARCHAR2)
   AUTHID CURRENT_USER
IS
   SEQ_NAME       VARCHAR2 (100);
   FINAL_QUERY    VARCHAR2 (100);
   COUNT_NUMBER   NUMBER := 0;
   cur_id         NUMBER;
BEGIN
   SEQ_NAME := 'SEQ_' || VAR_TAB_NAME;

   SELECT COUNT (*)
     INTO COUNT_NUMBER
     FROM USER_SEQUENCES
    WHERE SEQUENCE_NAME = SEQ_NAME;

   DBMS_OUTPUT.PUT_LINE (SEQ_NAME || '>' || COUNT_NUMBER);

   IF COUNT_NUMBER = 0
   THEN
      --DBMS_OUTPUT.PUT_LINE('DROP SEQUENCE ' || SEQ_NAME);
      -- EXECUTE IMMEDIATE 'DROP SEQUENCE ' || SEQ_NAME;
      -- ELSE
      SELECT 'CREATE SEQUENCE COMPTABILITE.' || SEQ_NAME || ' START WITH ' || ROUND (DBMS_RANDOM.VALUE (100000000000, 999999999999), 0) || ' INCREMENT BY 1'
        INTO FINAL_QUERY
        FROM DUAL;

      DBMS_OUTPUT.PUT_LINE (FINAL_QUERY);
      cur_id := DBMS_SQL.OPEN_CURSOR;
      DBMS_SQL.parse (cur_id, FINAL_QUERY, DBMS_SQL.v7);
      DBMS_SQL.CLOSE_CURSOR (cur_id);
   -- EXECUTE IMMEDIATE FINAL_QUERY;

   END IF;

   COMMIT;
END;
/

【讨论】:

【参考方案3】:

您可以在过程定义的主体中使用“AUTHID CURRENT_USER”来满足您的要求。

【讨论】:

【参考方案4】:

或者,如果需要,您可以授予用户DROP_ANY_TABLE 特权,并且该过程将按原样运行而无需任何更改。也许很危险,但取决于你在做什么:)

【讨论】:

除了那种首先使拥有特权的原因无效。此外,“DROP_ANY_TABLE”不太可能在任何大型公司的生产中随便授予。

以上是关于在存储过程中执行立即持续提供权限不足错误的主要内容,如果未能解决你的问题,请参考以下文章

oracle 在存储过程中用动态sql创建序列为何会遇到权限不足的问题呢?

尝试从包执行过程时出现权限不足错误

在存储过程中创建动态表而在 PL/SQL 块表中创建时权限不足[重复]

关于在存储过程中立即执行

作为系统用户,我遇到此错误:ORA-01031:权限不足

oracle 创建存储过程部分表编译错误是不是表空间、权限不足?