sql >> Databáze >  >> RDS >> Oracle

Porovnejte dvě schémata a aktualizujte staré schéma pomocí nových sloupců nového schématu

Nástroj pro porovnávání schémat je dobrý nápad. Databázové schéma je mnohem komplikovanější, než většina lidí uvádí, a každý rozdíl mezi dvěma schématy databáze může způsobit chyby.

Pokud to stále chcete udělat sami, nejlepší přístup, který jsem našel, je extrahovat definice schématu do textu a poté spustit porovnání textu. Pokud je vše seřazeno abecedně, můžete použít funkci Porovnat dokumenty v aplikaci Microsoft Word (nebo FC.EXE, DIFF nebo ekvivalentní), abyste rozdíly zvýraznili.

Následující skript SQLPlus vydává definici schématu abecedně, aby bylo možné porovnávat. Existují dvě sekce. V první části jsou uvedeny jednotlivé sloupce ve formátu:

table_name.column_name: data_type = data_default <nullable>

Druhá část uvádí následující indexy a omezení:

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)

Skript slouží jako užitečné reference pro extrahování některých podrobností schématu Oracle. To může být dobrá znalost, když jste mimo klientské stránky a nemáte k dispozici své obvyklé nástroje, nebo když vám bezpečnostní zásady brání v přístupu k databázi klientských stránek přímo z vašeho počítače.

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

Bohužel existuje několik omezení:

  1. Vložené návraty vozíku a mezery v data_defaults a definice omezení kontroly mohou být zvýrazněny jako rozdíly, i když nemají na schéma žádný vliv.
  2. Nezahrnuje alternativní klíče, jedinečné indexy nebo indexy výkonu. To by vyžadovalo třetí příkaz SELECT ve skriptu odkazující na zobrazení katalogu all_ind_columns a all_indexes.
  3. Nezahrnuje podrobnosti o zabezpečení, synonyma, balíčky, spouštěče atd. Balíčky a spouštěče by bylo nejlepší porovnat pomocí přístupu podobného tomu, který jste původně navrhli. Do výše uvedeného skriptu lze přidat další aspekty definice schématu.
  4. Výše uvedené definice FK identifikují odkazující sloupce cizího klíče, nikoli však odkazovaný PK nebo tabulku. Ještě jeden detail, ke kterému jsem se nikdy nedostal.

I když skript nepoužíváte. Hraní s těmito věcmi je pro techniky určité potěšení.;-)

Matěj



  1. Mysql Join 2 table a vyberte maximální a minimální hodnotu mezi časovým obdobím

  2. SQL dotaz s omezením na řádky z jedné tabulky, nikoli výsledkovou sadu

  3. MariaDB JSON_VALID() Vysvětleno

  4. Problém Django DateRangeField