web-dev-qa-db-ja.com

ストアドプロシージャ内で即時実行を実行すると、権限不足エラーが発生し続ける

ストアドプロシージャの定義は次のとおりです。

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コマンドの特権不足エラーが発生し続けます。オンラインで調べたところ、通常、権限不足エラーは、Oracleユーザーアカウントに、渡されるクエリ(この場合はDROP)で使用されるコマンドに対する権限がないことを意味することがわかりました。ただし、ドロップ権限があります。私は本当に混乱していて、自分に合った解決策を見つけることができないようです。

よろしくお願いします。

溶液:

スティーブが以下で言及したように、Oracleセキュリティモデルは、使用する特権の種類を手順のどこかに明示的に知る必要があるという点で奇妙です。 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;

皆さん、返信ありがとうございます。これは間違いなく、解決策を得るための非常に迷惑な問題でした。

35
tundal45

Oracleのセキュリティモデルでは、即時実行(PL/SQLブロックまたはプロシージャのコンテキスト内)を使用して動的SQLを実行する場合、ユーザーはロールメンバーシップを介して付与されるオブジェクトまたはコマンドに対する特権を持ちません。ユーザーには、おそらく「DBA」ロールまたはそれに類似した役割があります。このユーザーに「ドロップテーブル」権限を明示的に付与する必要があります。別のスキーマ(sysやsystemなど)のテーブルから選択しようとした場合も同じことが当てはまります。このテーブルに対する明示的なSELECT権限をこのユーザーに付与する必要があります。

18
Steve Broberg

この例を使用する必要があります 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

要件のプロシージャ定義の本文で「AUTHID CURRENT_USER」を使用できます。

4
adramazany

または、ユーザーにDROP_ANY_TABLE特権が必要な場合、プロシージャは変更なしでそのまま実行されます。危険かもしれませんが、あなたが何をしているかに依存します:)

0
Spellers