Newsgroup: it.comp.software.database
Titolo: [ORACLE] foreign Key

ho visto un po' in giro per quanto riguarda Oracle e le foreign key, ma
tutti i testi parlano solo di come impostare l'ON DELETE. Cioè a
quanto ho capito Oralce, non prevede la gestione delle chiavi esterne
nel caso esse vengano aggiornate, ma solo nel caso in cui esse vengano
cancellate.
CONSTRAINT fk_column
  FOREIGN KEY (column1, column2, ... column_n)
  REFERENCES parent_table (column1, column2, ... column_n)
  ON DELETE SET NULL
);
Posso inserire al di sotto di ON DELETE:
ON UPDATE CASCADE????

 
Ho fatto una interessante scoperta (almeno per me):
a quanto pare la possibilità di inserire la clausola "ON UPDATE..." non è stata prevista di proposito. Guarda questa
discussione su asktom:
http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:5773459616034
in cui si giustifica tale mancanza in base ad un principio per cui "le chiavi primarie devono essere immutabili".
Comunque ON UPDATE CASCADE può essere "simulato" con un package opportuno indicato nella discussione.
Ho notato però che Postgresql permette di utilizzare la clausola ON UPDATE.
Questa cosa mi ha lasciato un po' perplesso... probabilmente ho delle lacune teoriche: qualcuno sa in base a quale
principio le chiavi primarie devono essere immutabili? Io non ci vedrei nulla di male finché rimangono univoche.
Ciao.

 finché rimangono univoche.
Tom te lo spiega in modo abbastanza esauriente con il primo punto
(deferrable constraints).
Qui 
http://en.wikipedia.org/wiki/Primary_key
 invece non sembra che
l'immutabilità sia parte del modello relazionale, almeno nelle prime
versioni.
Bye
-- 
Rudy
http://rdbland.blogspot.com/
e-mail a 
email.it
*** JUST CERTIFIED *** :-)

 vedrei nulla di male finché rimangono univoche.
Dunque, mettiamo un po' di carne sul fuoco; io tendo a dividere
il modello relazionale in due parti: una parte di "data theory",
quella più formale, e una di "dbms management". La prima mi
interessa di più, in quanto spesso applicabile anche alla
programmazione.
Per la data theory, una chiave è un attributo con la riconosciuta
caratteristica di identificare univocamente una tupla.
Se si cambia un valore di un attributo, si può similmente cambiare
quello di una chiave.
Il concetto di "cambiare" è una semplificazione che sta nell'occhio
di chi guarda: una tupla, con solo con una "piccola" variazione, è
completamente un'altra tupla.
Pertanto, ogni variazione è (dovrebbe) essere teoricamente
equivalente ad una singola transazione di delete della
tupla + un corrispondente insert della "nuova" tupla.
Tale processo DEVE (dovrebbe) avere lo stesso risultato logico di
un update.
Se non ne siete convinti, provate ad immaginare di cancellare una
tupla, e di inserirne un'altra CON GLI STESSI VALORI.
Il database è cambiato?
Un teorico ci ragionerà e risponderà di NO
Un dba guarderà i log e risponderà di SI
(un neocertificato ocp non risponderà perché ormai sbronzo a
quest'ora :-))
Pertanto, la data theory relazionale è impermeabile ai concetti di
(im)mutabile, cambiare, simile, quasi uguale, molto diverso, etc...
La stabilità di una chiave primaria è questione di CONVENIENZA PRATICA.
Se immaginiamo una Partita Iva, risulterebbe assai spiacevole
cambiarla dopo aver stampato carta intestata, biglietti da visita
inviati in giro etc.
Per quanto riguarda il dbms management, ci si chiede se una qualunque
variazione in una pk debba essere automaticamente "propagata".
Credo di NO, almeno per quanto riguarda l'automatismo.
Il motivo è che una stessa operazione può avere SIGNIFICATI DIFFERENTI
a seconda delle impostazioni dello schema.
Facciamo un esempio (NOTA BENE: uso tabelle non normalizzate solo per
illustrare l'esempio)
Ordini {CodCliPK, NumOrd, Importo}  ---FK--->  Spedizioni {CodCli,
RifOrdine, Totale}
Ordini
------------------
Gino,  123, 10.000
(Pino, 123, 10.000)  <- riga non ancora presente
Spedizioni
----------------
Gino, 123, 9.000
Si supponga che ci si accorge che l'ordine già fatturato di Gino,
che ha un plafond per 10.000 Euro di merce ordinabile,
era in realtà stato ordinato da Pino, che ha un plafond di solo 500
Euro, ma l'ufficio spedizioni non ha potuto saperlo, ed ha già
spedito tranquillamente.
L'ufficio ordini vorrebbe "solo cambiare" il nome di chi ha
ordinato. Se la clausola CASCADE è attiva:
- Se faccio un UPDATE su Ordini cambierò la tupla in Spedizioni
facendo sembrare che ho spedito a Pino, IL CHE NON E' SUCCESSO
- Se cancello l'ordine di Gino per reinserirlo uguale come Pino,
SPARISCE una spedizione già effettuata e non ottengo l'effetto
di equivalente sostituzione logica.
Se la clausola CASCADE non è attiva, le stesse operazioni avverrano
diversamente CAMBIANDO LA SEMANTICA DEGLI STESSI MEDESIMI COMANDI,
il che non è accettabile.
Specialmente un update sulla tab. Ordini, ha un significato che
non è più _autocontenuto_, ma dipende da impostazioni esterne.
Che succede se entrambi i clienti hanno già ordini con spedizioni?
Ordini
----------------
Gino, 1, 10.000
Pino, 2, 500
Gino, 3, 8.000
Spedizioni
----------------
Gino, 9.000
Pino, 450
Gino, 8.500
Pino, 350
Con update sull'ordine 3 da Gino a Pino dovrebbe cambiare
*automaticamente* le relative spedizioni? Si? No? Dipende?
Semplicemente NON SI PUO' PIU' SAPERLO in anticipo: lo stesso
comando verrà interpretato differentemente, a seconda delle
impostazioni.
Bisogna riflettere sull'opportunità di inserire la funzionalità
di cascading nel comando UPDATE piuttosto che nello schema,
lasciando in questo modo decidere a chi impartisce il comando
cosa INTENDEVA DIRE.
bye

 quest'ora :-))
D'oh!
-- 
Rudy

 [esempio omesso]
Anche secondo me no. Non sempre. Ma una cosa è dire che /non sempre/ la modifica deve essere propagata automaticamente,
un altra è dire che non può essere /mai/ propagata. La decisione di inserire la clausola "ON UPDATE CASCADE" o "ON
DELETE CASCADE" fa parte del modello dei dati IMHO. Nel caso da te descritto come esempio la clausola non ci vuole
certamente: registrare un fatto vero tra gli ordini (pino ha ordinato per 10000 euro) implicherebbe registrare un fatto
falso nelle spedizioni (ho spedito a pino per 10000 euro). Ma in un modello tipo:
clienti(CodCli) CodCli PK
ordini(CodCli, RifOrdine, Totale) CodCli FK-->clienti(CodCli)
clienti
--------
Gino
Lino
Ordini
-------
Gino, 123, 10.000
Lino, 124, 500
Qual'è la controindicazione nell'accorgersi che Gino in realtà si chiama Pino (errore di battitura) e propagare la
modifica agli ordini (a parte le controindicazioni esterne al database di cui sopra)?
Forse sono un po' duro a capire ma mi piace comprendere a fondo le cose.
Ciao

 database di cui sopra)?
Nessuna in questo caso. Ma ti propongo un altro esempio:
Clienti {Nome}
Ordini {Nome FK, OrdNum}
Spedizioni {Nome FK, RifOrd FK}
 clienti
 --------
 Gino
 Lino
 Ordini
 -------
 Gino, 123
 Lino, 124
 Spedizioni
 -----------
 Gino, 123
 Lino, 124
Se io volessi cambiare un ordine da Lino a Gino, cambierei anche
a chi l'ho spedita, il che è indesiderabile (se l'ho già spedita,
non posso fermarla). Questo è un esempio di automatismo indesiderato.
Il problema è: lo sa chi cambia la tabella Ordini, che sta anche
variando una spedizione? No, appunto, ed è questo il punto.
Se si vuole che la modifica si propaghi, dovrebbe essere specificato
A MANO, dato che con un singolo update della tabella Ordini posso
intendere cose differenti:
1) l'ordinante è sbagliato, ma la spedizione ormai non si può cambiare
2) l'ordinante è sbagliato, la spedizione si cambia (merce non
ancora spedita)
Se i cascade sono attivi, vai sul punto 2 ANCHE SE NON
LO VUOI E/O NON LO SAI. Se invece la clausola cascade è nel
comando di update, sei sicuro dell'effetto che avrà.
bye