Oracle
 sql >> Database >  >> RDS >> Oracle

Confronta due schemi e aggiorna il vecchio schema con le nuove colonne del nuovo schema

Uno strumento di confronto degli schemi è una buona idea. Lo schema del database è molto più complicato di quanto la maggior parte delle persone attribuisca e ogni differenza tra due schemi di database può potenzialmente causare bug.

Se sei ancora desideroso di farlo da solo, l'approccio migliore che ho trovato è estrarre le definizioni dello schema in testo, quindi eseguire un confronto del testo. Finché tutto è ordinato in ordine alfabetico, puoi quindi utilizzare la funzione Confronta documenti in Microsoft Word (o FC.EXE, DIFF o equivalente), per evidenziare le differenze.

Il seguente script SQLPlus restituisce la definizione dello schema in ordine alfabetico, per consentire il confronto. Ci sono due sezioni. La prima sezione elenca ogni colonna, nel formato:

table_name.column_name: data_type = data_default <nullable>

La seconda sezione elenca indici e vincoli, come segue:

PK constraint_name on table_name (pk_column_list)
FK constraint_name on table_name (fk_column_list)
CHECK constraint_name on table_name (constraint_definition)

Lo script funge da utile riferimento per estrarre alcuni dettagli dello schema Oracle. Questa può essere una buona conoscenza da avere quando sei nei siti dei clienti e non hai i tuoi soliti strumenti disponibili o quando le politiche di sicurezza ti impediscono di accedere al database di un sito client direttamente dal tuo PC.

set serveroutput on;
set serveroutput on size 1000000;
declare
  rowcnt    pls_integer := 0;
  cursor c_column is
     select table_name, column_name, data_type, 
        data_precision, data_length, data_scale, 
        data_default, nullable,
        decode(data_scale, null, null, ',') scale_comma,
        decode(default_length, null, null, '= ') default_equals
      from all_tab_columns where owner = 'BCC'
      order by table_name, column_name;
  cursor c_constraint is
      select c.table_name, c.constraint_name,
         decode(c.constraint_type,
                'P','PK',
                'R','FK',
                'C','CHECK',
                 c.constraint_type) constraint_type,
         c.search_condition, 
         cc.column_1||cc.comma_2||cc.column_2||cc.comma_3||cc.column_3||cc.comma_4||cc.column_4||
         cc.comma_5||cc.column_5||cc.comma_6||cc.column_6||cc.comma_7||cc.column_7 r_columns   
       from all_constraints c,
          ( select owner, table_name, constraint_name, nvl(max(position),0) max_position,
             max( decode( position, 1, column_name, null ) ) column_1,
             max( decode( position, 2, decode(column_name, null, null, ',' ), null ) ) comma_2,
             max( decode( position, 2, column_name, null ) ) column_2,
             max( decode( position, 3, decode(column_name, null, null, ',' ), null ) ) comma_3,
             max( decode( position, 3, column_name, null ) ) column_3,
             max( decode( position, 4, decode(column_name, null, null, ',' ), null ) ) comma_4,
             max( decode( position, 4, column_name, null ) ) column_4,
             max( decode( position, 5, decode(column_name, null, null, ',' ), null ) ) comma_5,
             max( decode( position, 5, column_name, null ) ) column_5,
             max( decode( position, 6, decode(column_name, null, null, ',' ), null ) ) comma_6,
             max( decode( position, 6, column_name, null ) ) column_6,
             max( decode( position, 7, decode(column_name, null, null, ',' ), null ) ) comma_7,
             max( decode( position, 7, column_name, null ) ) column_7
           from all_cons_columns
           group by owner, table_name, constraint_name ) cc
       where c.owner = 'BCC'
       and c.generated != 'GENERATED NAME'
       and cc.owner = c.owner
       and cc.table_name = c.table_name
       and cc.constraint_name = c.constraint_name
       order by c.table_name, 
          decode(c.constraint_type,
                 'P','PK',
                 'R','FK',
                 'C','CHECK',
                 c.constraint_type) desc, 
          c.constraint_name;
begin
  for c_columnRow in c_column loop
    dbms_output.put_line(substr(c_columnRow.table_name||'.'||c_columnRow.column_name||': '||
                         c_columnRow.data_type||'('||
                         nvl(c_columnRow.data_precision, c_columnRow.data_length)||
                         c_columnRow.scale_comma||c_columnRow.data_scale||') '||
                         c_columnRow.default_equals||c_columnRow.data_default||
                         ' <'||c_columnRow.nullable||'>',1,255));
    rowcnt := rowcnt + 1;
  end loop;
  for c_constraintRow in c_constraint loop
    dbms_output.put_line(substr(c_constraintRow.constraint_type||' '||c_constraintRow.constraint_name||' on '||
                         c_constraintRow.table_name||' ('||
                         c_constraintRow.search_condition||
                         c_constraintRow.r_columns||') ',1,255));
    if length(c_constraintRow.constraint_type||' '||c_constraintRow.constraint_name||' on '||
                         c_constraintRow.table_name||' ('||
                         c_constraintRow.search_condition||
                         c_constraintRow.r_columns||') ') > 255 then
       dbms_output.put_line('... '||substr(c_constraintRow.constraint_type||' '||c_constraintRow.constraint_name||' on '||
                            c_constraintRow.table_name||' ('||
                            c_constraintRow.search_condition||
                            c_constraintRow.r_columns||') ',256,251));
    end if;
    rowcnt := rowcnt + 1;
  end loop;
end;
/

Sfortunatamente, ci sono alcune limitazioni:

  1. I ritorni a capo e gli spazi bianchi incorporati in data_defaults e le definizioni dei vincoli di controllo possono essere evidenziati come differenze, anche se non hanno alcun effetto sullo schema.
  2. Non include chiavi alternative, indici univoci o indici delle prestazioni. Ciò richiederebbe una terza istruzione SELECT nello script, che faccia riferimento alle viste del catalogo all_ind_columns e all_indexes.
  3. Non include dettagli di sicurezza, sinonimi, pacchetti, trigger, ecc. È meglio confrontare i pacchetti e i trigger utilizzando un approccio simile a quello originariamente proposto. Altri aspetti della definizione dello schema potrebbero essere aggiunti allo script precedente.
  4. Le definizioni FK precedenti identificano le colonne della chiave esterna di riferimento, ma non la PK o la tabella a cui si fa riferimento. Solo un dettaglio in più che non ho mai avuto modo di fare.

Anche se non usi lo script. C'è un certo piacere tecnico nel giocare con questa roba.;-)

Matteo