2009-06-15 9 views
32

Ecco la definizione della stored procedure:Esecuzione immediata all'interno di una stored procedure continua a dare privilegi insufficienti errore

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; 

Ecco la chiamata:

Per qualche ragione, continuo a ricevere insufficiente errore di privilegi per il comando ESEGUIRE IMMEDIATO. Ho cercato online e ho scoperto che l'errore di privilegi insufficiente di solito significa che l'account utente oracle non ha privilegi per il comando utilizzato nella query che passa, che in questo caso è DROP. Tuttavia, ho i privilegi di drop. Sono davvero confuso e non riesco a trovare una soluzione che funzioni per me.

Grazie a voi in anticipo.

SOLUZIONE:

Come Steve menzionato qui di seguito, modello di sicurezza Oracle è strano in quanto ha bisogno di sapere in modo esplicito da qualche parte nel procedimento che tipo di privilegi da utilizzare. Il modo per far sapere a Oracle che è usare la parola chiave AUTHID nell'istruzione CREATE OR REPLACE. Se si desidera lo stesso livello di privilegi del creatore della procedura, si utilizza AUTHID DEFINER. Se si desidera che Oracle utilizzi i privilegi dell'utente che esegue attualmente la procedura memorizzata, si desidera utilizzare AUTHID CURRENT_USER. La dichiarazione della procedura è la seguente:

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; 

Grazie a tutti per aver risposto. Questo era sicuramente un problema molto fastidioso per arrivare alla soluzione.

+0

stavo affrontando problema simile, ma la cosa divertente è senza usare 'AUTHID DEFINER' o 'AUTHID CURRENT_USER' la procedura è stata in esecuzione per il drop table affermazione ma non per creare tabella. La soluzione AUTHID funziona :) Grazie! – Aniket

+0

Grazie, queste due parole "AUTHID CURRENT_USER" risolvono il mio problema! Grazie! – Roman

risposta

15

Il modello di sicurezza di Oracle è tale che quando si esegue SQL dinamico utilizzando Execute Immediate (nel contesto di un blocco o procedura PL/SQL), l'utente non dispone di privilegi per oggetti o comandi concessi tramite l'appartenenza al ruolo. Il tuo utente probabilmente ha un ruolo "DBA" o qualcosa di simile. È necessario concedere esplicitamente autorizzazioni "drop table" a questo utente. Lo stesso si applica se stavi provando a selezionare da tabelle in un altro schema (come sys o system) - avresti bisogno di concedere espliciti privilegi SELECT su quella tabella a questo utente.

+1

Grazie per la risposta. Ho provato 'ESEGUIRE IMMEDIATO ('GRANT drop table ON' || schema_name || '.' || tblToDrop || 'TO ben');' ma sto ricevendo errore di privilegio non valido per quella linea. Ho cercato online l'assegnazione del privilegio al drop table ma non riesco a trovare nulla. Ho provato tutti e "drop table" ma ottengo lo stesso errore. Sai dove posso trovare il nome del privilegio giusto o cosa sto facendo male qui? Grazie ancora. – tundal45

+1

Non utilizzare EXECUTE IMMEDIATE per concedere il privilegio.È necessario concedere il privilegio di drop table a BEN: GRANT DROP TABLE a BEN –

+3

Steve, Ho appena capito. Risulta che potrei definire i privilegi all'interno della procedura utilizzando AUTHID. Se desidero gli stessi privilegi del creatore, utilizzo AUTHID DEFINER. Se desidero i privilegi dell'utente corrente, utilizzo AUTHID CURRENT_USER. Ecco come il guscio procedimento appare: creare o sostituire PROCEDURA some_procedure AUTHID CURRENT_USER IS BEGIN DECLARE BEGIN END; END; – tundal45

0

In alternativa è possibile concedere il privilegio utente DROP_ANY_TABLE se necessario e la procedura verrà eseguita così com'è senza la necessità di alcuna modifica. Pericoloso, ma dipende da cosa stai facendo :)

+0

Ad eccezione di quel tipo di invalidazione, la ragione per cui si hanno privilegi in primo luogo. Inoltre, è improbabile che "DROP_ANY_TABLE" venga concesso casualmente in produzione per qualsiasi azienda di dimensioni significative. –

3

potresti utilizzare "AUTHID CURRENT_USER" nel corpo della definizione della procedura in base alle tue esigenze.

2

Si consiglia di utilizzare questo esempio con 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; 
/
Problemi correlati