ストアドプロシージャの定義は次のとおりです。
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;
皆さん、返信ありがとうございます。これは間違いなく、解決策を得るための非常に迷惑な問題でした。
Oracleのセキュリティモデルでは、即時実行(PL/SQLブロックまたはプロシージャのコンテキスト内)を使用して動的SQLを実行する場合、ユーザーはロールメンバーシップを介して付与されるオブジェクトまたはコマンドに対する特権を持ちません。ユーザーには、おそらく「DBA」ロールまたはそれに類似した役割があります。このユーザーに「ドロップテーブル」権限を明示的に付与する必要があります。別のスキーマ(sysやsystemなど)のテーブルから選択しようとした場合も同じことが当てはまります。このテーブルに対する明示的なSELECT権限をこのユーザーに付与する必要があります。
この例を使用する必要があります 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
特権が必要な場合、プロシージャは変更なしでそのまま実行されます。危険かもしれませんが、あなたが何をしているかに依存します:)