2011-11-24 19 views
23

Eliminerò i dati in una tabella di SQL Server (parent) che ha una relazione con un'altra tabella (secondaria).
Ho provato la query Elimina di base. Ma non funziona (e so che non lo farà).Elimina dati con chiave esterna nella tabella di SQL Server

DELETE FROM table WHERE ... 

è tornata seguente errore

L'istruzione DELETE in conflitto con il vincolo RIFERIMENTO ...

ho bisogno di mantenere lo schema della tabella. So che ho solo bisogno di aggiungere alcune parole nella query, l'ho mai fatto prima, ma non riuscivo proprio a ricordarlo.

risposta

12

Se si desidera che l'eliminazione sia automatica, è necessario modificare lo schema in modo che il vincolo di chiave esterna sia ON DELETE CASCADE.

Per ulteriori informazioni, vedere MSDN page on Cascading Referential Integrity Constraints.

ETA (dopo il chiarimento dal poster): se non è possibile aggiornare lo schema, è necessario innanzitutto ELIMINARE manualmente i record figlio interessati.

+0

ah. Mi è mancato di raccontare quella parte del mio post, devo farlo funzionare senza modificare lo schema. è possibile vero? – Andha

+1

No, non è possibile con qualche query magica OPTION o altro. È necessario eseguire manualmente le eliminazioni. –

28

È possibile disattivare e riattivare i vincoli di chiave esterna, prima e dopo l'eliminazione:

alter table MyOtherTable nocheck constraint all 
delete from MyTable 
alter table MyOtherTable check constraint all 
+5

Se si disabilita, quindi riattivare i vincoli, la riattivazione non verrà interrotta a causa dei riferimenti 'estranei' 'rotti '? –

+0

No, controlla solo il vincolo quando si scrivono nuovi valori in un campo: non esegue nuovamente la scansione dell'intera tabella quando si inserisce nuovamente il controllo. –

+3

Bene. Ciò significa che tutti i dati nella tabella figlio rimarranno lì. Sto per eliminare 2k righe e penso che sarà ingombrante se tengo i dati nella tabella figlio. Penso che lo farò solo manualmente. Comunque comunque per le risposte ragazzi. Ti meriti +1 :) – Andha

2

Quindi, è necessario DELETE righe correlate da tabelle in conflitto o più logico UPDATE loro colonna FOREIGN KEY fare riferimento ad altre PRIMARY KEY è dalla tabella dei genitori.

Inoltre, si consiglia di leggere questo articolo Don’t Delete – Just Don’t

26

È necessario eliminare manualmente i bambini. lo <condition> è lo stesso per entrambe le query.

DELETE FROM child 
FROM cTable AS child 
INNER JOIN table AS parent ON child.ParentId = parent.ParentId 
WHERE <condition>; 

DELETE FROM parent 
FROM table AS parent 
WHERE <condition>; 
+0

È possibile combinare questi due DELETE in modo che sia necessario scrivere la parte una sola volta? –

+1

Non ci credo, @ThomasTempelmann. Se vuoi scrivere la condizione solo una volta, devi attivare le eliminazioni a cascata invece di occuparti manualmente di ciascuna tabella. La risposta di Alastair Maw qui fa riferimento anche a questa opzione. –

2

Per eliminare i dati dalle tabelle che hanno rapporto di parent_child, prima devi cancellare i dati dalla tabella figlio menzionando iscriviti poi semplicemente cancellare i dati dalla tabella padre, ad esempio è il seguente:

DELETE ChildTable 
FROM ChildTable inner join ChildTable on PParentTable.ID=ChildTable.ParentTableID 
WHERE <WHERE CONDITION> 


DELETE ParentTable 
WHERE <WHERE CONDITION> 
+0

Questa è la migliore risposta se non si esegue la cancellazione a cascata. I cursori funzionano in modo orribile e la rimozione dei vincoli da eliminare potrebbe lasciare file orfani in altre tabelle. – Corv1nus

5

qui si sta aggiungendo la chiave esterna per la tabella "Child"

ALTER TABLE child 
ADD FOREIGN KEY (P_Id) 
REFERENCES parent(P_Id) 
ON DELETE CASCADE 
ON UPDATE CASCADE; 

Dopo di che, se si effettua una query DELETE sulla tabella "Parent" come questo

DELETE FROM parent WHERE ..... 

dal momento che il bambino ha un riferimento al genitore con CASCADE DELETE, le righe "figlio" sarà anche essere cancellato! insieme al "genitore".

1

sceneggiatura Utile quale è possibile eliminare tutti i dati in tutte le tabelle di un database, sostituire tt con te nome databse:

declare @tablename nvarchar(100) 
declare c1 cursor for 
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_CATALOG='tt' AND TABLE_TYPE='BASE TABLE' 

open c1 
fetch next from c1 into @tablename 

while @@FETCH_STATUS = 0 
    begin 
    print @t1 
     exec('alter table ' + @tablename + ' nocheck constraint all') 
     exec('delete from ' + @tablename) 
     exec ('alter table ' + @tablename + ' check constraint all') 
     fetch next from c1 into @tablename 
    end 
close c1 
DEALLOCATE c1 
Problemi correlati