2009-06-15 37 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; 
/