2010-02-05 3 views
9

Lo sviluppatore principale di un progetto in cui sono coinvolto dice che è una cattiva pratica affidarsi a cascate per eliminare le righe correlate.È errato affidarsi a una cascata di chiavi estranee?

Non vedo come questo sia male, ma mi piacerebbe conoscere i tuoi pensieri su se/perché è.

+0

Possibile duplicato di [Quando/Perché utilizzare Cascading in SQL Server?] (Http://stackoverflow.com/questions/59297/when-why-to-use-cascading-in-sql-server). Inoltre, tendo a concordare molto di più con le risposte dell'altra domanda, che sono molto diverse da quelle qui. –

risposta

14

Prevedo questo dicendo che raramente elimino le righe periodo. Generalmente la maggior parte dei dati si desidera conservare. Basta contrassegnarlo come cancellato in modo che non venga mostrato agli utenti (ad es. Appare cancellato). Naturalmente dipende dai dati e per alcune cose (ad es. Il contenuto del carrello) in realtà eliminando i record quando l'utente svuota il suo carrello va bene.

Posso solo supporre che il problema qui sia che si possa cancellare involontariamente i record che non si desidera eliminare. L'integrità referenziale dovrebbe tuttavia impedirlo. Quindi non riesco davvero a vedere un motivo contro questo diverso dal fatto che sia esplicito.

+0

Qui devo concordare con Cletus, a meno che non ci sia un problema di capacità legale o reale ... l'archiviazione è così a buon mercato e veloce raramente c'è un vero motivo per fare una cancellazione difficile in questi giorni. +1 –

+4

Ecco uno dei motivi: i dati cancellati che rientrano nei risultati della query perché qualcuno ha dimenticato un 'AND DELETED = 0'. Se lo fai, nascondi tutti i dati cancellati dietro una vista solo dati in tempo reale o simili, oppure ** ti imbatterai in problemi. –

+0

@Michael - Dipende dalla tua architettura, ad esempio ho un progetto linq, e nei modelli T4 è banale aggiungere una chiamata al metodo di estensione '.Current()' nei riferimenti 'DataContext.GetTable ' che genera. Ho potuto vedere come questo sarebbe un problema in altre situazioni, ma non * sempre *. –

5

Non uso mai eliminazioni a cascata. Perché? Perché è troppo facile fare un errore. Molto più sicuro di richiedere applicazioni client per esplicitamente eliminare (e soddisfare le condizioni per l'eliminazione, come ad esempio l'eliminazione di FK cui record.)

In realtà, le eliminazioni di per sé può essere evitato segnando record come cancellati o si spostano in tabelle di archivio/storia.

Nel caso di marcatura record come cancellati, esso dipende la proporzione relativa dei contrassegnato come dati cancellati, poiché SELECT s dovranno filtrare 'isDeleted = false' un indice sarà usato solo se meno del 10% (approssimativamente, a seconda dell'RDBMS) dei record sono contrassegnati come cancellati.

Quale di questi 2 scenari si preferisce:

1) sviluppatore viene a voi, dice: "Ehi, questo elimina non funzionerà". Entrambi la esaminano e scoprono che sta cercando accidentalmente di cancellare l'intero contenuto della tabella. Entrambi ridete e tornate a quello che stavate facendo.

2) Lo sviluppatore viene da te e chiede timidamente "Abbiamo dei backup?"

+0

da quando cancelleresti dati banali? I dati banali sono in genere statici. Questo argomento non regge. –

+0

Diciamo che sto eseguendo il backup di un ordine dal sistema: Ordine -> Elementi pubblicitari -> Commenti. Se cancello l'ordine (prompt di conferma nell'app, naturalmente), le righe nelle altre 2 tabelle sono ora inutili. Se non si è impostato il ripristino del record genitore (nel qual caso, non si sta eliminando ...) spesso i bambini non contano più, è più facile effettuare una cascata eliminarli tutti insieme in un colpo di database dall'inizio. Come ho detto, questione di applicazione e opinione, ma loro ** fanno ** hanno i loro usi. –

+0

+1 per "Abbiamo dei backup?" – Neolisk

10

Direi che segui il principio della sorpresa minima.

Le eliminazioni a cascata non devono causare perdite impreviste di dati. Se un'eliminazione richiede che i record correlati vengano eliminati e l'utente deve sapere che tali record stanno per essere eliminati, le eliminazioni a cascata non dovrebbero essere utilizzate. Invece, all'utente dovrebbe essere richiesto di eliminare esplicitamente i record correlati o di ricevere una notifica.

D'altra parte, se la tabella si riferisce a un'altra tabella di natura temporanea o che contiene record che non saranno mai necessari una volta che l'entità padre è stata eliminata, le eliminazioni in cascata potrebbero essere corrette.

Detto questo, preferisco dichiarare esplicitamente le mie intenzioni eliminando i relativi record nel codice, piuttosto che fare affidamento su eliminazioni a cascata. In effetti, non ho mai utilizzato effettivamente un'elencazione a cascata per eliminare implicitamente i record correlati. Inoltre, uso molto la cancellazione soft, come descritto da cletus.

+0

Questo è un buon principio, ci sono abbastanza sorprese naturali, non c'è bisogno di produrne altre – Rawheiser

1

Un altro motivo enorme per evitare le eliminazioni a cascata è la prestazione. Sembrano una buona idea finché non è necessario eliminare 10.000 record dalla tabella principale che a loro volta hanno milioni di record nelle tabelle figlio.Data la dimensione di questa eliminazione, è probabile che blocchi completamente tutto il tavolo per ore forse anche per giorni. Perché mai rischieresti questo? Per la comodità di spendere dieci minuti in meno di tempo a scrivere le istruzioni di cancellazione extra per una cancellazione record?

Inoltre, l'errore che si ottiene quando si tenta di eliminare un record con un record figlio è spesso una buona cosa. Ti dice che non vuoi cancellare questo record perché ci sono dati che ti servono che potresti perdere se lo facessi. Eliminazione in cascata andrebbe avanti e cancellerebbe i record figlio con conseguente perdita di informazioni sugli ordini, ad esempio se hai eliminato un cliente che aveva ordini in passato. Questo genere di cose può rovinare completamente i tuoi dati finanziari.

+0

Non capisco il tuo primo scenario, come sarebbe il lavoro alternativo che eviterebbe l'overhead perfetto? record figlio? O è il fatto che un'eliminazione blocca in qualche modo le tabelle che causano il problema, e separa le eliminazioni evita questo? –

+0

Si farebbero le eliminazioni dalle tabelle figlio in batch e poi l'eliminazione principale. mai utilizzare la cancellazione a cascata in un database di tipo Enterprise di produzione È semplicemente troppo probabile che causi un problema di produzione – HLGEM

+0

In caso di più righe che devono essere eliminate (nella tabella di riferimento), se possibile, le prestazioni delle eliminazioni a catena sarebbero meglio, il tuo codice non verrà eseguito più velocemente di quello nel DB. L'altro scenario è strano per me - non puoi "erroneamente" cancellare referenc ing file. Se hai dichiarato un FK come a cascata, significa che è tua intenzione non permettere che le righe di referenziamento esistano senza quella di riferimento, che è un caso d'uso completamente accettabile. –

0

Mi è stato anche detto che le eliminazioni a cascata erano pratiche sbagliate ... e quindi non li ho mai utilizzati fino a quando non mi sono imbattuto in un cliente che li ha usati. Non sapevo davvero perché non dovevo usarli, ma pensavo che fossero molto comodi nel non dover codificare la cancellazione di tutti i record FK.

Così ho deciso di cercare perché erano così "cattivi" e da quello che ho trovato finora il loro non sembra essere qualcosa di problematico su di loro. In effetti, l'unica buona argomentazione che ho visto fino ad ora è ciò che HLGLEM ha affermato sopra sulle prestazioni. Ma poiché di solito non sto eliminando questo numero di record, penso che nella maggior parte dei casi il loro utilizzo dovrebbe andare bene. Mi piacerebbe sapere di altri argomenti che potrebbero essere gli altri contro il loro utilizzo per assicurarmi di aver preso in considerazione tutte le opzioni.

+1

Il problema con la cascata su eliminazione è, se si elimina accidentalmente un valore dalla tabella di riferimento, tutte le righe che utilizzano tale valore verranno eliminate (non solo il valore in quelle righe ma l'intera riga). Sembra davvero stupido, ma ho appena imparato questo nel modo più duro oggi. – Holonaut

+0

@ Holonaut Vedo quello che stai dicendo, sarebbe un problema. Ma vedo lo stesso problema che si verifica se si cancella accidentalmente un record in modo programmatico, come faccio di solito con il clic del pulsante. –