使用Oracle中的存储过程删除特定表

时间:2014-02-24 22:43:05

标签: oracle plsql oracle11g

我很困惑。我有一个用户可以在SQL Developer中运行下面的程序,它运行正常。

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;

2 个答案:

答案 0 :(得分:1)

最有可能的是,这是一个特权问题。

ALL_TABLES列出您拥有权限的所有表。以交互方式运行时,包括您通过角色拥有的所有表。但是,当您尝试创建存储过程时,将排除通过角色授予的权限,并且您只能看到直接授予的那些表。如果希望代码有效,则对象(或DBA)的所有者需要将对象的权限直接授予过程所有者,而不是通过角色。实际上,该过程的所有者还需要直接授予它的DROP ANY TABLE权限(而不是通过像DBA这样的角色)才能使DROP TABLE语句成功。

答案 1 :(得分:1)

贾斯汀是对的。但是你经常可以使用AUTHID来克服私有问题。尝试:

CREATE OR REPLACE PROCEDURE DELETETEMPTABLES
AUTHID CURRENT_USER
AS

这在Oracle中称为“调用者权限”。默认值为definers权限(authid definer)。有关详情,请参阅herehere

  

在子程序中使用角色取决于它是否执行   定义者的权利或赋权者的权利。在定义者的权利范围内   子程序,所有角色都被禁用。角色不用于特权   检查,你不能设置角色。

     

在调用者权利子程序中,角色已启用(除非   子程序由定义者权利直接或间接调用   子程序)。角色用于权限检查,您可以使用   本机动态SQL,用于设置会话的角色。但是,你做不到   使用角色为模板对象授予权限,因为角色适用   在运行时,而不是在编译时。