2010-03-01 12 views
7

Ho bisogno di eseguire una serie di (fino a ~ 1000000) istruzioni SQL su un database Oracle. Queste istruzioni dovrebbero risultare in uno stato referenzialmente coerente alla fine e tutte le istruzioni dovrebbero essere ripristinate in caso di errore. Queste dichiarazioni non sono in un ordine referenziale. Quindi, se i vincoli di chiave esterna sono abilitati, una delle istruzioni può causare una violazione di chiave esterna anche se, questa violazione sarebbe stata corretta con un'istruzione che sarebbe stata eseguita in seguito.Oracle DDL in un'operazione autonoma

Ho provato disabilitando chiavi esterne prima e consentendo loro dopo sono state eseguite tutte le istruzioni. Pensavo di poter tornare indietro quando si verificava una violazione effettiva della chiave esterna. Avevo però torto, ho scoperto che ogni istruzione DDL in Oracle iniziava con un commit, quindi non c'era modo di ripristinare le istruzioni in questo modo. Qui è il mio script per la disattivazione chiavi esterne:

begin 
    for i in (select constraint_name, table_name from user_constraints 
      where constraint_type ='R' and status = 'ENABLED') 
    LOOP execute immediate 'alter table '||i.table_name||' disable constraint 
          '||i.constraint_name||''; 
    end loop; 
end; 

Dopo alcune ricerche, ho scoperto che è stato raccomandato di eseguire istruzioni DDL, come in questo caso, in una transazione autonoma. Così ho provato a eseguire istruzioni DDL in una transazione autonoma. Ciò ha provocato il seguente errore:

ORA-00054: risorsa occupata e acquisire con NOWAIT specificato

Sto indovinando questo è perché l'operazione principale ha ancora blocco DDL sui tavoli.

sto facendo qualcosa di sbagliato qui, o c'è altro modo per fare questo lavoro scenario?

risposta

8

Esistono diversi potenziali approcci.

La prima cosa da considerare è che qualunque cosa tu faccia a livello di tabella si applicherà a tutte le sessioni usando quella tabella. Se non hai accesso esclusivo a quella tabella, probabilmente non vuoi eliminare/ricreare i vincoli o disabilitarli/abilitarli.

La seconda cosa da considerare è che probabilmente non si vuole essere in una posizione di rollback un milione di inserti/aggiornamenti. Il rollback può essere lento.

Generalmente vorrei caricare in una tabella temporanea. Quindi fai un singolo INSERT dalla tabella temporanea nella tabella di destinazione. Come singola affermazione, Oracle applicherà tutti i vincoli di controllo alla fine.

Se non è possibile passare attraverso una tabella temporanea (ad es. Aggiornamenti di dati esistenti), prima di iniziare, effettuare i vincoli deferrable initially immediate. Quindi, all'interno della sessione,

SET CONSTRAINTS emp_job_nn, emp_salary_min DEFERRED; 

È quindi possibile applicare le modifiche e, quando si esegue il commit, i vincoli verranno convalidati.

Si dovrebbe aquaint te stesso con DML error logging in quanto può aiutare a identificare le righe che causano violazioni.

+0

ho appena scoperto il trucco "SET vincoli" ed è venuto qui per rispondere alla mia domanda, e ho visto la tua risposta :). Grazie. – swamplord

Problemi correlati