sql >> Databasteknik >  >> RDS >> Oracle

Jämför två scheman och uppdatera det gamla schemat med de nya kolumnerna i det nya schemat

Ett verktyg för schemajämförelse är en bra idé. Databasschemat är mycket mer komplicerat än vad de flesta ger kredit, och varje skillnad mellan två databasscheman har potential att orsaka buggar.

Om du fortfarande är sugen på att göra det själv är det bästa sättet jag har hittat att extrahera schemadefinitionerna till text och sedan köra en textjämförelse. Så länge allt är sorterat i alfabetisk ordning kan du sedan använda funktionen Jämför dokument i Microsoft Word (eller FC.EXE, DIFF eller motsvarande) för att markera skillnaderna.

Följande SQLPlus-skript matar ut schemadefinitionen alfabetiskt för att möjliggöra jämförelse. Det finns två sektioner. Det första avsnittet listar varje kolumn, i formatet:

table_name.column_name: data_type = data_default <nullable>

Det andra avsnittet listar index och begränsningar enligt följande:

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)

Skriptet fungerar som en användbar referens för att extrahera några av Oracle-schemadetaljerna. Detta kan vara bra att ha när du är ute på klientwebbplatser och du inte har dina vanliga verktyg tillgängliga, eller när säkerhetspolicyer hindrar dig från att komma åt en klientwebbplatsdatabas direkt från din egen dator.

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;
/

Tyvärr finns det några begränsningar:

  1. Inbäddade vagnreturer och blanksteg i data_defaults, och kontrollbegränsningsdefinitioner, kan markeras som skillnader, även om de inte har någon effekt på schemat.
  2. Innehåller inte alternativa nycklar, unika index eller prestandaindex. Detta skulle kräva en tredje SELECT-sats i skriptet, som hänvisar till all_ind_columns och all_indexes katalogvyer.
  3. Innehåller inte säkerhetsdetaljer, synonymer, paket, utlösare etc. Paket och utlösare skulle bäst jämföras med ett tillvägagångssätt som liknar det du ursprungligen föreslog. Andra aspekter av schemadefinitionen kan läggas till ovanstående skript.
  4. FK-definitionerna ovan identifierar referenskolumnerna för främmande nyckel, men inte PK eller tabellen som refereras till. Bara en detalj till som jag aldrig hann göra.

Även om du inte använder skriptet. Det finns ett visst tekniskt nöje att leka med det här.;-)

Matteus



  1. Hur man skapar index för dynamiska söksträngar

  2. python models.py syncdb fungerar inte

  3. Hur konfigurerar jag DbContext för att fungera med Oracle ODP.Net och EF CodeFirst?

  4. Oracle:SÄTT PÅ SERVEROUTPUT med Padda