web-dev-qa-db-fra.com

Exécuter immédiatement dans une procédure stockée continue de donner une erreur de privilèges insuffisants

Voici la définition de la procédure stockée:

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;

Voici l'appel:

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

Pour une raison quelconque, je continue à obtenir une erreur de privilèges insuffisants pour la commande EXECUTE IMMEDIATE. J'ai regardé en ligne et j'ai découvert que l'erreur de privilèges insuffisants signifie généralement que le compte d'utilisateur Oracle n'a pas de privilèges pour la commande utilisée dans la requête qui est réussie, qui dans ce cas est DROP. Cependant, j'ai des privilèges d'abandon. Je suis vraiment confus et je n'arrive pas à trouver une solution qui fonctionne pour moi.

Merci d'avance.

SOLUTION:

Comme Steve l'a mentionné ci-dessous, le modèle de sécurité d'Oracle est étrange en ce qu'il doit savoir explicitement quelque part dans la procédure quel type de privilèges utiliser. La façon de faire savoir à Oracle que d'utiliser le mot clé AUTHID dans l'instruction CREATE OR REPLACE. Si vous voulez le même niveau de privilèges que le créateur de la procédure, vous utilisez AUTHID DEFINER. Si vous souhaitez qu'Oracle utilise les privilèges de l'utilisateur exécutant actuellement la procédure stockée, vous souhaitez utiliser AUTHID CURRENT_USER. La déclaration de procédure se présente comme suit:

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;

Merci à tous d'avoir répondu. C'était définitivement un problème très ennuyeux pour arriver à la solution.

35
tundal45

Le modèle de sécurité d'Oracle est tel que lors de l'exécution de SQL dynamique à l'aide d'Execute Immediate (dans le contexte d'un bloc ou d'une procédure PL/SQL), l'utilisateur n'a pas de privilèges sur les objets ou les commandes accordés via l'appartenance au rôle. Votre utilisateur a probablement un rôle "DBA" ou quelque chose de similaire. Vous devez explicitement accorder des autorisations de "dépôt de table" à cet utilisateur. La même chose s'appliquerait si vous tentiez de sélectionner des tables dans un autre schéma (tel que sys ou système) - vous auriez besoin d'accorder des privilèges SELECT explicites sur cette table à cet utilisateur.

18
Steve Broberg

Vous devez utiliser cet exemple avec 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;
/
6
Chakib Arrama

vous pouvez utiliser "AUTHID CURRENT_USER" dans le corps de votre définition de procédure pour vos besoins.

4
adramazany

Vous pouvez également accorder à l'utilisateur DROP_ANY_TABLE privilège si nécessaire et la procédure se déroulera telle quelle sans qu'il soit nécessaire de la modifier. Dangereux peut-être mais cela dépend de ce que vous faites :)

0
Spellers