以下是存储过程的定义:
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;
谢谢大家的回复。这对于解决方案来说肯定是非常恼人的问题。
答案 0 :(得分:17)
Oracle的安全模型是这样的,当使用Execute Immediate执行动态SQL时(在PL / SQL块或过程的上下文中),用户不具有通过角色成员资格授予的对象或命令的权限。您的用户可能具有“DBA”角色或类似的东西。您必须向此用户明确授予“drop table”权限。如果您尝试从另一个模式(例如sys或system)中的表中进行选择,则同样适用 - 您需要将该表的显式SELECT权限授予此用户。
答案 1 :(得分:4)
您应该将此示例与 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 :(得分:3)
你可以使用" AUTHID CURRENT_USER"在您的程序定义的正文中为您的要求。
答案 3 :(得分:0)
或者,如果需要,您可以授予用户DROP_ANY_TABLE
权限,并且该过程将按原样运行,而无需进行任何更改。危险可能,但取决于你在做什么:)