我很困惑。 我有一个用户可以在SQL开发人员中运行以下内容,并且运行良好。
begin
FOR C IN (SELECT TABLE_NAME FROM ALL_TABLES
WHERE TABLE_NAME LIKE 'TEMP_%'
AND OWNER = '<user name in caps>')
LOOP
EXECUTE IMMEDIATE('DROP TABLE <user name in caps>.' || C.table_name || ' PURGE');
END LOOP;
end;
但是 - 如果我将功能包装在存储过程中并运行它,同时没有引发异常,则以"temp"开头的表不会删除。 我实际上正在从三个不同的模式中删除 - 因此重复。
CREATE OR REPLACE PROCEDURE DELETETEMPTABLES AS
BEGIN
--DROP ANY TABLES THAT START WITH "TEMP_"
FOR C IN (SELECT TABLE_NAME FROM ALL_TABLES
WHERE TABLE_NAME LIKE 'TEMP_%'
AND OWNER = '<user name in caps>')
LOOP
EXECUTE IMMEDIATE('DROP TABLE <user name in caps>.' || C.table_name || ' PURGE');
END LOOP;
FOR C IN (SELECT TABLE_NAME FROM ALL_TABLES
WHERE TABLE_NAME LIKE 'TEMP_%'
AND OWNER = '<user name in caps>')
LOOP
EXECUTE IMMEDIATE('DROP TABLE <user name in caps>.' || C.table_name || ' PURGE');
END LOOP;
FOR C IN (SELECT TABLE_NAME FROM ALL_TABLES
WHERE TABLE_NAME LIKE 'TEMP_%'
AND OWNER = '<user name in caps>')
LOOP
EXECUTE IMMEDIATE('DROP TABLE <user name in caps>.' || C.table_name || ' PURGE');
END LOOP;
exception
WHEN OTHERS THEN
log_errors (p_error_message => 'Nightly Processing->DeleteTempTables-> ' ||SQLERRM);
END DELETETEMPTABLES;
贾斯汀是正确的。 但是您通常可以使用AUTHID来克服隐私问题。 尝试:
CREATE OR REPLACE PROCEDURE DELETETEMPTABLES
AUTHID CURRENT_USER
AS
这在 Oracle 中称为"调用者权限"。 默认值为定义者权限(authid definer)。 有关更多信息,请参阅此处和此处。
在子程序中角色的使用取决于它是否使用 定义者的权利或调用者的权利。在定义者的权利范围内 子程序,所有角色都被禁用。角色不用于特权 选中,并且无法设置角色。
在调用者的权限子程序中,将启用角色(除非 子程序直接或间接地由定义者的权利调用 子程序)。角色用于权限检查,您可以使用 本机动态 SQL,用于设置会话的角色。但是,您不能 使用角色授予对模板对象的权限,因为角色适用 在运行时,而不是在编译时。
最有可能的是,这是一个特权问题。
ALL_TABLES
列出了您有权访问的所有表。 以交互方式运行它时,这包括您通过角色拥有权限的所有表。 但是,当您尝试创建存储过程时,将排除通过角色授予的权限,并且您只能看到您直接授予的那些表。 如果希望代码正常工作,则对象的所有者(或 DBA)需要直接向过程所有者授予对象的权限,而不是通过角色授予权限。 实际上,过程的所有者还需要直接授予它的DROP ANY TABLE
特权(而不是通过像DBA
这样的角色),DROP TABLE
语句才能成功。