简体   繁体   中英

Check whether a tables exist or not on another schema - ORACLE DB

I've a stored procedure created by EMP_DBA and part of the query will check whether the existing tables exist or not, if exist then drop table. This query works fine if I connect as EMP_DBA, now I want to run this stored procedure with other account let say USER1 and I've grant all the necessary rights to USER1. How to rewrite below statement in order count return 1 if the table MARKET_DATA exist in schema EMP_DBA ?

BEGIN 
SELECT COUNT(*) INTO c
FROM all_tables
WHERE
table_name = 'MARKET_DATA' AND OWNER = 'EMP_DBA';

IF C = 1 THEN
EXECUTE IMMEDIATE 'DROP TABLE MARKET_DATA';
--exception when others then null; 
END IF;

Your select is correct. You should rewrite the EXECUTE IMMEDIATE to do

DROP TABLE EMP_DBA.MARKET_DATA

"I've grant all the necessary rights to USER1"

This is a slightly worrying statement. What do you mean by all the necessary rights ? The only appropriate right is execute on a stored procedure owned by EMP_DBA. That procedure should encapsulate everything. EMP_DBA doesn't (or shouldn't) want USER1to drop their tables independently. Besides it isn't possible to grant DDL statements on specific objects, or even specific schemas. And DROP ANY is a powerful privilege to hand out.

The best way to write the stored procedure is to use definer's rights (which is the default). This ensures that the code is executed with the privileges of the stored procedure's owner, not those of the executing user. That your code doesn't work - presumably because you haven't specified the table owner - suggests you haven't got your security model quite right.

In my version I've used ALL_TABLES just like you did, to show the difference between CURRENT_USER and SESSION_USER, but actually USER_TABLES would work just as well.

create or replace procedure recreate_tab
    (p_tab_name in all_tables.table_name%type)
    authid definer
is
    n pls_integer;
begin
    select count(*)
    into n
    from all_tables
    where owner = (sys_context('userenv','current_user'))
    and table_name = p_tab_name;

    if n = 1
    then
        -- no need to specify schema because it's the procedure owner
        execute immediate 'drop table '|| p_tab_name;
    end if;

    execute immediate 'create table '||p_tab_name
        ||' ( id number, descr varchar2(30))';

    -- grant rights on the new table to the user executing the procedure
    execute immediate 'grant select on '||p_tab_name||' to '
        || sys_context('userenv','session_user');
end recreate_tab;
/

grant execute on recreate_tab to user1
/

So. Nothing up my sleeve ...

SQL> conn user1/user1
Connected.
SQL> select count(*) from t42
  2  /
select count(*) from t42
             *
ERROR at line 1:
ORA-00942: table or view does not exist


SQL> select count(*) from emp_dba.t42
  2  /

  COUNT(*)
----------
     56179

SQL> exec emp_dba.recreate_tab('T42')

PL/SQL procedure successfully completed.

SQL> select count(*) from emp_dba.t42
  2  /

  COUNT(*)
----------
     0

SQL> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM