If I create a procedure:
CREATE OR REPLACE PROCEDURE SchameB.PRC_GATHER_STATS IS
BEGIN
SYS.DBMS_STATS.GATHER_TABLE_STATS( 'SchName', 'TableName', CASCADE => TRUE);
END;
and execute it ;
EXEC SchameB.PRC_GATHER_STATS;
this gives me error ORA-20000: Unable to analyze TABLE "SchameA"."TableName", insufficient privileges or does not exist
. But this works:
EXEC SYS.DBMS_STATS.GATHER_TABLE_STATS( 'SchameA', 'TableName', CASCADE => TRUE);
The user who EXEC
s the procedure and the table are in different schemas.
Why am I getting an error when doing this through a procedure?
To gather stats in oracle we require to use the DBMS_STATS package.It will collect the statistics in parallel with collecting the global statistics for partitioned objects. The DBMS_STATS package specialy used only for optimizer statistics.
SCHEMA level exec DBMS_STATS. FLUSH_DATABASE_MONITORING_INFO; select OWNER,TABLE_NAME,LAST_ANALYZED,STALE_STATS from DBA_TAB_STATISTICS where STALE_STATS='YES' and OWNER='&owner; set timing on exec dbms_stats. gather_schema_stats(ownname=>'&schema_name', CASCADE=>TRUE,ESTIMATE_PERCENT=>dbms_stats.
The idea behind estimate_percent is to gather a statistically representative sample size. Below we use the default estimate_percent. auto_sample_size, which minimizes overhead while at the same time giving a statistically significant sample size.
To gather statistics on an object in another schema you need the ANALYZE ANY
system privilege. I appears that the user that runs your procedure has that privilege, but granted through a role. As the documentation says:
All roles are disabled in any named PL/SQL block (stored procedure, function, or trigger) that executes with definer's rights.
You can either GRANT ANALYZE ANY
directly to your user, or create the procedure with invoker's rights, as:
CREATE OR REPLACE PROCEDURE SchameB.PRC_GATHER_STATS
AUTHID CURRENT_USER IS
BEGIN
SYS.DBMS_STATS.GATHER_TABLE_STATS('SchName', 'TableName', CASCADE => TRUE);
END;
/
When you EXEC
the DBMS_STATS
procedure directly, it's running as an anonymous block, and those always run with invoker's rights - honouring roles.
If you want the procedure to be able to be ran by a user without the ANALYSE ANY
role then you can set the AUTHID
to be DEFINER
CREATE OR REPLACE PROCEDURE SchameB.PRC_GATHER_STATS
AUTHID DEFINER IS
BEGIN
SYS.DBMS_STATS.GATHER_TABLE_STATS('SchName', 'TableName', CASCADE => TRUE);
END;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With