Procedure not processing 'table exists' exception handler in plsql

Viewed 20

I've created a procedure to create backup tables which is failing to pick up the IF statement under the 'table_exists' exception handler. It is meant to drop and recreate the backup table if it already exists AND the do_not_delete column in the user.record table is set to 'NO':

{CREATE OR REPLACE PROCEDURE USER.CREATE_BACKUP_TABLE (t_owner varchar2, t_name varchar2, t_retention number, t_can_delete_tag varchar2) as
/*
*******************************************************************************************************
Object Name:  CREATE_BACKUP_TABLE
*/-- Private variables
icnt         number;
sqlcmd       varchar2(1000);
backup_table varchar2(1000);
l_affx       varchar2(30) := 'BKP';
l_date       varchar2(30) := to_char(sysdate,'yyyy_mm_dd');
table_exists exception;
table_does_not_exist exception;
pragma exception_init(table_exists, -00955);
pragma exception_init(table_does_not_exist, -00942);
l_delete USER.RECORD.DO_NOT_DELETE%type;
--
--
begin
for tn in (
select table_name, owner
  from all_tables
where table_name = t_name
   and owner = t_owner
)
LOOP
    BEGIN
    backup_table := tn.owner||'.'||tn.table_name||'_'||l_date||'_'||l_affx;
    sqlcmd := 'create table '||backup_table||' AS SELECT * FROM '||tn.owner||'.'||tn.table_name;
    dbms_output.put_line(sqlcmd);
    execute immediate sqlcmd;
    --
    exception
    when table_exists then
       sqlcmd := 'select do_not_delete into :l_delete from user.record where backup_table = '''||backup_table||'''';
       execute immediate sqlcmd;
       if l_delete = 'NO' then
       sqlcmd := 'drop table '||backup_table||' cascade constraints';
       dbms_output.put_line(sqlcmd);
       execute immediate sqlcmd;
       sqlcmd := 'create table '||backup_table||' AS SELECT * FROM '||tn.owner||'.'||tn.table_name;
       execute immediate sqlcmd;
              else if l_delete = 'YES' then
              dbms_output.put_line('DML Action: Rollback');
              Rollback;
              end if;
                  end if;
                       when others then
                       dbms_output.put_line('ERROR: Preceeding statement failed with '||substr(sqlerrm(sqlcode),1,120));
                       dbms_output.put_line('DML Action: Rollback');
                       Rollback;
end;
   END LOOP;
end;
/}
1 Answers

It's not the correct way to get the result from an execute immediate: use "execute immediate ... returning into..." instead. And by the way, in your case you don't need to use execute immediate to get the do_not_delete value, you can "select ... into " directly since the name of the table in the FROM clause is not a variable.

Related