bulk collect und for loop / Constraints ab- und wieder anschalten

Manchen Operationen (wie z.B. truncate oder drop partition) können nicht mit aktiven Constraints auf die Tabelle ausgeführt werden.
Daher hat sich folgender Ablauf bewährt:
- aktive Constraints abzuschalten
- eigentliches Drop / truncate
- obige Constraints wieder einschalten
(Idealerweise "merkt" man sich die betroffenen Constraints und schaltet nicht pauschal alle Constraints wieder ein.)

Im Code kann das dann so aussehen:

Vorab - Typen definieren und Fehlerhandling vorbereiten
-- Type für Drop_Partition_FS definieren
  -- Datentypen aus SYS.ALL_CONSTRAINTS
  type x IS
    record
    (
      OWNER VARCHAR2 (128 Char),
      TABLE_NAME VARCHAR2 (128 Char),
      CONSTRAINT_NAME VARCHAR2 (128 Char),
      STATUS VARCHAR2 (8 Char)) ;

  type y IS
    TABLE OF x;
    z y;

-- globale Variablen
  part_missed EXCEPTION;
  PRAGMA EXCEPTION_INIT (part_missed, -2149);
  
  v_Sql     varchar2(4000);  -- SQL-String


Eigentliche Umsetzung:
  -- FK-Constraints auf die Tabelle bestimmen; Status merken
  select C1.OWNER
       , C1.TABLE_NAME
       , C1.CONSTRAINT_NAME
       , C1.STATUS
    bulk collect into z
    from sys.ALL_CONSTRAINTS c1, sys.ALL_CONSTRAINTS c2
   where     c1.constraint_type = 'R'
         and c2.constraint_type in ('P', 'U')
         and c2.owner = 'mySchema'
         and c2.table_name = p_myTbl
         and c1.r_owner = c2.owner
         and c1.r_constraint_Name = c2.constraint_name
   order by 1,2,3;
  
  -- aktive Constraints abschalten
  for i in 1..z.count
  loop
    if z(i).STATUS = 'ENABLED' then 
      v_Sql := 'alter table '||z(i).OWNER||'.'||z(i).TABLE_NAME||' disable constraint '||z(i).CONSTRAINT_NAME ||' keep index';
      log(c_Modul, v_Sql);
      execute immediate v_Sql;
    end if;
  end loop; 
  
  -- eigentliches Partition droppen
  v_Sql := 'alter table '||p_Tbl_Name||' drop partition '||p_Partition_Name;
  log(c_Modul, v_Sql);
  begin 
    execute immediate v_Sql;
  exception
    when part_missed then null;
    when others then raise;
  end;

  -- vorher aktive Constraints wieder einschalten
  for i in 1..z.count
  loop
    if z(i).STATUS = 'ENABLED' then 
      v_Sql := 'alter table '||z(i).OWNER||'.'||z(i).TABLE_NAME||' enable novalidate constraint '||z(i).CONSTRAINT_NAME;
      log(c_Modul, v_Sql);
      execute immediate v_Sql;
    end if;
  end loop; 


Hinweis:
  for i in 1..z.count
-> Falls der Select ggfs. keine (aktiven) Constraint findet führt
  for i in i.first..i.last
zu einem Fehler (da i leer ist).

Kommentare

Beliebte Posts aus diesem Blog

PGA unter Oracle 11g

trunc(sysdate) - nette Spiele mit dem Datum

Datapump - Verzeichnis erstellen