Exécuter immédiatement dans le cadre d'une procédure stockée continue de donner des privilèges insuffisants erreur

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 à avoir des erreurs de privilèges insuffisants pour exécuter la commande immédiate. J'ai regardé en ligne et j'ai découvert que l'erreur de privilèges insuffisants signifie habituellement que le compte d'utilisateur oracle n'a pas de privilèges pour la commande utilisée dans la requête qui est passe, qui dans ce cas est DROP. Cependant, j'ai des privilèges de largage. Je suis vraiment confus et je n'arrive pas à trouver une solution qui fonctionne pour moi.

Merci à l'avance de vous.

SOLUTION:

comme Steve l'a mentionné ci-dessous, le modèle de sécurité 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 le faire savoir à Oracle est d'utiliser le mot-clé AUTHID dans la déclaration CREATE ou 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 voulez Oracle pour utiliser les privilèges de l'utilisateur qui exécute actuellement la procédure stockée, vous voulez 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 certainement un problème très ennuyeux pour arriver à la solution.

34
demandé sur tundal45 2009-06-15 17:45:31

4 réponses

le modèle de sécurité D'Oracle est tel que lors de L'exécution de SQL dynamique en utilisant Execute Immediate (dans le contexte D'un bloc ou d'une procédure PL/SQL), l'utilisateur n'a pas de privilèges aux objets ou aux commandes qui sont accordés via l'adhésion de rôle. Votre Utilisateur a probablement un rôle "DBA" ou quelque chose de similaire. Vous devez explicitement accorder les permissions "drop table" à cet utilisateur. Il en irait de même si vous essayiez de sélectionner des tableaux dans un autre schéma (tel que sys ou system) - vous auriez besoin d'accorder des privilèges de sélection explicites sur cette table pour cet utilisateur.

17
répondu Steve Broberg 2009-06-15 15:16:55

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

3
répondu adramazany 2016-08-21 09:07:05

Vous devriez 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;
/
2
répondu Chakib Arrama 2017-05-18 08:56:17

Sinon, vous pouvez accorder à l'utilisateur DROP_ANY_TABLE privilège si besoin est et la procédure se déroulera telle quelle sans qu'aucune modification ne soit nécessaire. Dangereux peut-être, mais tout dépend de ce que vous faites :)

0
répondu Spellers 2012-11-20 13:14:07