Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

exec gather table stats from procedure

Tags:

oracle

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 EXECs the procedure and the table are in different schemas.

Why am I getting an error when doing this through a procedure?

like image 801
Deniz Avatar asked Jan 31 '13 11:01

Deniz


People also ask

How do you run gather stats on a table in Oracle?

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.

How do you run gather stats on a schema?

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.

What is estimate_percent in gather 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.


2 Answers

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.

like image 117
Alex Poole Avatar answered Sep 18 '22 14:09

Alex Poole


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;
like image 26
zlsmith86 Avatar answered Sep 16 '22 14:09

zlsmith86