从过程中执行收集表统计信息

6
如果我创建了一个过程:
CREATE OR REPLACE PROCEDURE SchameB.PRC_GATHER_STATS IS
BEGIN
    SYS.DBMS_STATS.GATHER_TABLE_STATS( 'SchName', 'TableName', CASCADE => TRUE);
END;

执行它;

EXEC SchameB.PRC_GATHER_STATS;

这会给我一个错误:ORA-20000: 无法分析表 "SchameA"."TableName",权限不足或不存在。但是这个可以正常工作:

EXEC SYS.DBMS_STATS.GATHER_TABLE_STATS( 'SchameA', 'TableName', CASCADE => TRUE);

执行存储过程的用户和表位于不同的模式中。

为什么执行该存储过程时会出现错误?


不太确定我是否理解正确;但是你是否依赖于通过角色授予的权限,在你的过程中可能不适用?(链接:http://docs.oracle.com/cd/E25054_01/network.1111/e16543/authorization.htm#autoId16) - Alex Poole
我理解了,那么我该如何将其应用到程序中呢? - Deniz
2个回答

9
要收集另一个架构中对象的统计信息,您需要拥有ANALYZE ANY系统特权。看起来运行您过程的用户具有该特权,但是通过角色授权的。正如文档所说

在以定义者权限执行的任何命名PL/SQL块(存储过程、函数或触发器)中,所有角色都被禁用。

您可以直接将GRANT ANALYZE ANY授予您的用户,或按照以下方式使用调用者权限创建过程:文档链接
CREATE OR REPLACE PROCEDURE SchameB.PRC_GATHER_STATS
AUTHID CURRENT_USER IS
BEGIN
    SYS.DBMS_STATS.GATHER_TABLE_STATS('SchName', 'TableName', CASCADE => TRUE);
END;
/

当您直接执行DBMS_STATS过程时,它会作为匿名块运行,并且这些块始终以调用者的权限运行 - 尊重角色。


3

如果您希望用户能够运行该过程,而无需具有“ANALYSE ANY”角色,则可以将AUTHID设置为DEFINER


注:AUTHID是指在创建程序时定义程序的执行权限。若将其设置为DEFINER,则程序将使用创建者的权限进行执行。
CREATE OR REPLACE PROCEDURE SchameB.PRC_GATHER_STATS
AUTHID DEFINER IS
BEGIN
    SYS.DBMS_STATS.GATHER_TABLE_STATS('SchName', 'TableName', CASCADE => TRUE);
END;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接