Execute Immediate в хранимой процедуре продолжает выдавать ошибку недостаточных привилегий

Вот определение хранимой процедуры:

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;

Вот звонок:

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

По какой-то причине я продолжаю получать ошибку недостаточных привилегий для команды EXECUTE IMMEDIATE. Я посмотрел в Интернете и обнаружил, что ошибка недостаточных привилегий обычно означает, что учетная запись пользователя оракула не имеет привилегий для команды, используемой в передаваемом запросе, в данном случае это DROP. Тем не менее, у меня есть права на сброс. Я действительно запутался, и я не могу найти решение, которое работает для меня.

Спасибо вам заранее.

РЕШЕНИЕ:

Как Стив упомянул ниже, модель безопасности Oracle странна в том смысле, что ей нужно явно где-то в процедуре знать, какие привилегии использовать. Чтобы сообщить об этом Oracle, нужно использовать ключевое слово AUTHID в операторе CREATE OR REPLACE. Если вам нужен тот же уровень привилегий, что и у создателя процедуры, используйте 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;

Спасибо всем за ответы. Это была определенно очень раздражающая проблема, чтобы найти решение.


person Community    schedule 15.06.2009    source источник
comment
Я столкнулся с аналогичной проблемой, но самое смешное, что без использования «AUTHID DEFINER» или «AUTHID CURRENT_USER» процедура выполнялась для инструкции удаления таблицы, но не для создания таблицы. Решение AUTHID работает :) Спасибо!   -  person Aniket    schedule 21.08.2012
comment
Спасибо, эти два слова AUTHID CURRENT_USER решают мою проблему! Спасибо!   -  person Roman    schedule 17.02.2014


Ответы (4)


Модель безопасности Oracle такова, что при выполнении динамического SQL с помощью Execute Immediate (внутри контекста блока или процедуры PL/SQL) пользователь не имеет привилегий для объектов или команд, которые предоставляются через членство в роли. Ваш пользователь, вероятно, имеет роль «DBA» или что-то подобное. Вы должны явно предоставить этому пользователю разрешение на удаление таблицы. То же самое применимо, если вы пытаетесь выбрать из таблиц в другой схеме (например, sys или system) — вам нужно будет предоставить этому пользователю явные привилегии SELECT для этой таблицы.

person Community    schedule 15.06.2009
comment
Спасибо за ответ. Я пробовал EXECUTE IMMEDIATE('GRANT drop table ON ' || schema_name || '.' || tblToDrop || ' TO ben');, но получаю сообщение об ошибке недопустимых привилегий для этой строки. Я искал в Интернете назначение права на удаление таблицы, но ничего не нашел. Я пробовал все и удалял таблицу, но получаю ту же ошибку. Знаете ли вы, где я могу найти правильное имя привилегии или что я здесь делаю неправильно? Еще раз, спасибо. - person tundal45; 15.06.2009
comment
Не используйте EXECUTE IMMEDIATE для предоставления привилегии. Вам необходимо предоставить BEN привилегию удаления таблицы: GRANT DROP TABLE TO BEN - person Steve Broberg; 15.06.2009
comment
Стив, я только что понял. Оказывается, я мог определить привилегии внутри процедуры, используя AUTHID. Если мне нужны те же привилегии, что и у создателя, я использую AUTHID DEFINER. Если мне нужны привилегии текущего пользователя, я использую AUTHID CURRENT_USER. Вот как выглядит оболочка процедуры: CREATE OR REPLACE PROCEDURE some_procedure AUTHID CURRENT_USER IS BEGIN DECLARE BEGIN END; КОНЕЦ; - person tundal45; 16.06.2009
comment
@SteveBroberg В моем вопросе все привилегии GRANT, которые у меня есть, потому что я использую схему пользователя. stackoverflow.com/questions/57070212/ - person Md Wasi; 17.07.2019

Вы должны использовать этот пример с 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;
/
person Community    schedule 18.05.2017

вы можете использовать «AUTHID CURRENT_USER» в теле определения вашей процедуры для ваших требований.

person Community    schedule 21.08.2016

В качестве альтернативы вы можете предоставить пользователю привилегию DROP_ANY_TABLE, если это необходимо, и процедура будет выполняться без каких-либо изменений. Опасно, может быть, но зависит от того, что вы делаете :)

person Community    schedule 04.06.2011
comment
За исключением того, что в первую очередь это делает недействительной причину наличия привилегий. Кроме того, маловероятно, что DROP_ANY_TABLE будет случайно предоставлено в производстве какой-либо крупной корпорации. - person David Keener; 10.03.2015