在存储过程中执行立即保持不足的权限错误

tun*_*l45 35 sql privileges stored-procedures oracle10g

以下是存储过程的定义:

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;
Run Code Online (Sandbox Code Playgroud)

这是电话:

CALL usp_dropTable('SOMESCHEMA', 'SOME_TABLE');
Run Code Online (Sandbox Code Playgroud)

出于某种原因,我继续为EXECUTE IMMEDIATE命令获得不足的权限错误.我在线查看并发现权限不足的错误通常意味着oracle用户帐户没有对通过的查询中使用的命令的权限,在这种情况下是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;
Run Code Online (Sandbox Code Playgroud)

谢谢大家的回复.这对于解决方案来说肯定是非常烦人的问题.

Ste*_*erg 18

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

  • 史蒂夫,我刚想通了.事实证明我可以使用AUTHID在过程中定义权限.如果我想要与创建者相同的权限,我使用AUTHID DEFINER.如果我想要当前用户的权限,我使用AUTHID CURRENT_USER.过程shell的外观如下:CREATE OR REPLACE PROCEDURE some_procedure AUTHID CURRENT_USER BEGIN DECLARE BEGIN END; 结束; (5认同)
  • 不要使用EXECUTE IMMEDIATE授予特权。您需要将删除表特权授予BEN:GRANT DROP TABLE TO BEN (2认同)

Cha*_*ama 6

您应该将此示例与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;
/
Run Code Online (Sandbox Code Playgroud)


小智 5

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