2009-06-15 38 views
32

这里是存储过程的定义:执行即时在存储过程中不断给特权时不足错误

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; 

这里是呼叫:

出于某种原因,我不断收到不足EXECUTE IMMEDIATE命令的权限错误。我查看了联机状态,发现权限不足通常意味着oracle用户帐户对查询中使用的传递命令(在本例中为DROP)没有权限。不过,我有权限下降。我很困惑,我似乎无法找到适合我的解决方案。

感谢您提前。

SOLUTION:

正如史蒂夫下文提到,甲骨文的安全模型是怪异的,因为它需要知道使用什么样的权限,程序明确的地方。让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; 

谢谢大家的回复。这是解决问题的绝对烦人的问题。

+0

我正面临着类似的问题,但有趣的是,不使用“AUTHID DEFINER”或“AUTHID CURRENT_USER”的过程,对于DROP TABLE执行声明,但不适用于创建表。 AUTHID解决方案有效:)谢谢! – Aniket 2012-08-21 18:16:38

+0

谢谢,这两个字“AUTHID CURRENT_USER”解决了我的问题!谢谢! – Roman 2014-02-17 18:07:56

回答

15

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

+1

感谢您的回复。我尝试 `执行IMMEDIATE('授予drop表ON'|| schema_name ||''|| tblToDrop ||'TO本');` 但我得到该行无效特权错误。我在网上查找分配特权放弃表,但我似乎无法找到任何东西。我尝试了所有和“下降表”,但我得到了同样的错误。你知道我在哪里可以找到正确的特权名称或我在这里做错了什么吗?再一次感谢你。 – tundal45 2009-06-15 16:15:44

0

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

3

你可以在你的程序定义正文中使用“AUTHID CURRENT_USER”来满足你的需求。

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; 
/