Questo post è la traduzione in italiano per ITOUG del post Unknown constraint type on Toad for Oracle.

In questo post voglio rivedere velocemente uno dei concetti base di un RDBMS: i vincoli.

Questo mi ha permesso di spiegare una strana situazione accaduta realmente su un database di produzione.

Quanti tipi di vincoli possiamo utilizzare in un Database Oracle?

Possiamo utilizzare sei tipi di vincoli:

TipoFunzione
NOT NULL Il campo deve contenere un valore
UNIQUENessuna riga duplicata con lo stesso valore per quel campo/campi
PRIMARY KEYNOT NULL + UNIQUE
FOREIGN KEYValorne nel campo abbinato al campo padre
CHECKSpecifica validazione per il campo/campi
REFReferenza ad un oggetto
Oracle Constraints

Fin qui niente di nuovo, forse il constraint REF meno conosciuto e non richiesto per l’esame di certificazione SQL.

Come si può vedere dall’immagine sotto navigando i vincoli di una tablla utilizzando Toad schema browser possiamo notare un constraint disabilitato di nome SYS_C0052585 di tipo ?

Questo è uno scenario reale di un DB di produzione e cosa è successo qui?

Un utente vede un vincolo disabilitato e fino a qui nulla di particolarmente strano se non fosse per il tipo di vincolo.

Il vincolo di tipo ?

Che diavolo è questo vincolo? Lo posso rimuovere in maniera sicura? Tanto è disabilitato no? mmm… cancellare qualcosa in produzione potrebbe essere una pessima mosse. Meglio controllare ancora.

A questo punto l’utente da un’occhiata alla vista DBA_CONSTRAINTS ma non trova nessun vincolo chiamato SYS_C0052585.

Ok a questo punto l’utente si convince che il vincolo non esiste, lo cancella e….

Cosa è accaduto? La replica per la tabella in oggetto smette di funzionare e inizia a squillare il telefono. In questo caso specifico il tool di replica IBM CDC (Change Data Capture) smette di replicare gli statement di update nella tabella di destinazione.

A questo punto sorge spontanea la domanda come è possibile che la rimozione di un vincolo disabilitato e “apparentemente” invisibile nel dizionario dati può rompere qualcosa di questo genere?

Proviamo con questo esempio per riprodurre il problema

create table MY_TABLE(
 FIELD1 varchar(20),
 FIELD2 number not null,
 FIELD3 date);

 alter table MY_TABLE modify FIELD1 primary key;
sembra corretto ma facciamo un doppio controllo con…
select * from dba_constraints where table_name like 'MY_TABLE';
sembra tutto corretto

Ma come ho già detto questa tabella è una tabella speciale e vogliamo utilizzare un tool per fare una replica di questa tabella utilizzando il tool IBM Change Data Capture. Questo tool richiede di attivare la funzionalità di supplemental logging sul sorgente sia a livello di database sia a livello di tabella. Quindi non faccio altro che attivare il supplemental logging per tutte le colonne della mia tablella tramite

ALTER TABLE MY_TABLE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

A questo punto torno a dare uno sguardo ai vincoli della mia tabella tramite la vista DBA_CONSTRAINTS

E ancora per doppia conferma vado a guardare i vincoli su TOAD schema browser

vincolo disabilitato SYS_C007672 di tipo ? apparso

Cosa è successo? Un vincolo non presente nella vista DBA_CONSTRAINT è apparso.

Perchè?

Questo accade perche la vista DBA_CONSTRAINTS esclude alcuni tipi di vincoli identificati come “internals constraints” mentre TOAD schema browser ci fà vedere tutti i vincoli della tabella, internals inclusi.

Come dimostriamo questo e come possiamo avere maggiori informazioni?

Possiamo trovare maggiori informazioni nella tabella SYS.CON$ andando a cercare il nostro vincolo SYS_C007672.

select * from CON$ where name = 'SYS_C007672';

E utilizzando l’attributo CON# possiamo andare a filtrare una ricerca sulla tabella SYS.CDEF$

select * from CDEF$ where con#=7672;

Trovato! A questo punto per avere il quadro completo voglio selezionare tutti i vincoli della mia tabella.

select * from CDEF$ where con# in ('7665','7666','7672');

Nell’immagine ritroviamo tutti i vincoli della nostra tablella che differiscono per il campo TYPE#.

TYPE# = 2 for PRIMARY KEY constraints

TYPE# = 7 for NOT NULL constraints

TYPE# = 17 for ALL COLUMN SUPPLEMENTAL LOGGING constraints

Questo significa che Oracle fornisce 6 tipi di vincoli come si evince dalla documentazione ma implementa almeno 17 tipi di vincoli per usi interni.

Per la descrizione completa di tutti i vincoli compresi gli internals potete guardare in $ORACLE_HOME/rdbms/admin/dcore.bsq

Se l’articolo vi è piaciuto e vi va di approfondire la tematiche legate al supplemental logging e Golden Gate internals vi suggerisco di dare uno sguardo a questo articolo di Julian Dyke.