ストアドプロシージャ内で即時に実行すると、不十分な特権エラーが発生し続けます

StackOverflow https://stackoverflow.com/questions/996198

質問

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

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');

何らかの理由で、私は即時コマンドを実行するために不十分な特権エラーを取得し続けます。私はオンラインで見ましたが、特権エラーが不十分な場合、通常、Oracleユーザーアカウントが合格したクエリで使用されるコマンドの特権を持たないことを意味します。この場合はドロップされます。しかし、私はドロップ特権を持っています。私は本当に混乱しており、私に役立つ解決策を見つけることができないようです。

よろしくお願いします。

解決:

以下で述べたように、Oracle Securityモデルは、手順のどこかでどのような特権を使用するかを明示的に知る必要があるという点で奇妙です。 Oracleに、作成または交換ステートメントで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;

皆さんに返信していただきありがとうございます。これは、解決策に到達するための非常に迷惑な問題でした。

役に立ちましたか?

解決

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

他のヒント

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

要件の手順定義の本文で「authid current_user」を使用できます。

または、ユーザーに付与することもできます DROP_ANY_TABLE 必要に応じて特権があり、手順は変更を必要とせずに実行されます。危険かもしれませんが、あなたが何をしているのかに依存します:)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top