Search code examples
sqllinuxoracle-databaseshellsql-delete

Delete specific record from multiple child table(Not all child table) and then the parent table entry


I have a parent table name A and there are 47 child table which are referencing to this parent table A, i want to delete records from 23 child tables and then the parent table as well, and want to keep the records in the remaining child tables.

I tried doing this by disabling and enabling constraint but faced issue while enabling the constraint.

Can anyone suggest any better approach.

NOTE: I am trying to achieve this via shell script.


Solution

  • Keyword here is ENABLE NOVALIDATE. It'll let you keep "invalid" existing data, but referential integrity will be enforced for newly added rows.

    Here's an example.

    Master and two detail tables:

    SQL> create table master
      2    (id_mas number primary key,
      3     name varchar2(20));
    
    Table created.
    
    SQL> create table det_1
      2    (id_det number primary key,
      3     id_mas number constraint fk_d1_mas references master (id_mas),
      4     name varchar2(20));
    
    Table created.
    
    SQL> create table det_2
      2    (id_det number primary key,
      3     id_mas number constraint fk_d2_mas references master (id_mas),
      4     name varchar2(20));
    
    Table created.
    
    SQL>
    

    Sample rows:

    SQL> insert into master (id_mas, name)
      2  select 1, 'Little' from dual union all
      3  select 2, 'Foot'   from dual;
    
    2 rows created.
    
    SQL> insert into det_1 (id_det, id_mas, name)
      2  select 100, 1, 'Lit det 1'  from dual union all
      3  select 101, 1, 'Tle det 1'  from dual union all
      4  select 102, 2, 'Foot det 1' from dual;
    
    3 rows created.
    
    SQL> insert into det_2 (id_det, id_mas, name)
      2  select 200, 1, 'Lit det 2'  from dual union all
      3  select 201, 2, 'Tle det 2'  from dual union all
      4  select 202, 2, 'Foot det 2' from dual;
    
    3 rows created.
    
    SQL> commit;
    
    Commit complete.
    
    SQL>
    

    Now, let's delete ID_MAS = 1 from DET_1 and MASTER, but keep it in DET_2:

    Deleting from detail table is OK (why wouldn't it be?):

    SQL> delete from det_1 where id_mas = 1;
    
    2 rows deleted.
    

    I can't delete from master table because of foreign key constraint from DET_2:

    SQL> delete from master where id_mas = 1;
    delete from master where id_mas = 1
    *
    ERROR at line 1:
    ORA-02292: integrity constraint (SCOTT.FK_D2_MAS) violated - child record found
    

    So, let's disable it:

    SQL> alter table det_2 disable constraint fk_d2_mas;
    
    Table altered.
    

    Deleting from master now succeeds:

    SQL> delete from master where id_mas = 1;
    
    1 row deleted.
    

    Re-enabling previously disabled constraint on DET_2 will fail because it contains row(s) whose ID_MAS doesn't exist in MASTER table any more:

    SQL> alter table det_2 enable constraint fk_d2_mas;
    alter table det_2 enable constraint fk_d2_mas
                                        *
    ERROR at line 1:
    ORA-02298: cannot validate (SCOTT.FK_D2_MAS) - parent keys not found
    

    As I said, use ENABLE NOVALIDATE:

    SQL> alter table det_2 enable novalidate constraint fk_d2_mas;
    
    Table altered.
    

    Tables' contents:

    SQL> select * from master;
    
        ID_MAS NAME
    ---------- --------------------
             2 Foot
    
    SQL> select * from det_1;
    
        ID_DET     ID_MAS NAME
    ---------- ---------- --------------------
           102          2 Foot det 1
    
    SQL> select * from det_2;
    
        ID_DET     ID_MAS NAME
    ---------- ---------- --------------------
           200          1 Lit det 2         --> this master doesn't exist any more
           201          2 Tle det 2
           202          2 Foot det 2
    
    SQL>
    

    Let's try to insert some new (valid and invalid) rows:

    SQL> insert into det_1 (id_det, id_mas, name)
      2  select 110, 2, 'Valid' from dual;
    
    1 row created.
    
    SQL> insert into det_1 (id_det, id_mas, name)
      2  select 111, 1, 'Invalid' from dual;
    insert into det_1 (id_det, id_mas, name)
    *
    ERROR at line 1:
    ORA-02291: integrity constraint (SCOTT.FK_D1_MAS) violated - parent key not
    found
    
    
    SQL> insert into det_2 (id_det, id_mas, name)
      2  select 210, 2, 'Valid' from dual;
    
    1 row created.
    
    SQL> insert into det_2 (id_det, id_mas, name)
      2  select 211, 1, 'Invalid' from dual;
    insert into det_2 (id_det, id_mas, name)
    *
    ERROR at line 1:
    ORA-02291: integrity constraint (SCOTT.FK_D2_MAS) violated - parent key not
    found
    
    
    SQL>
    

    I am trying to achieve this via shell script.

    A shell script? What does shell have to do with that? It is Oracle's business.