Ricerca…


ON DELETE CASCADE

Supponi di avere un'applicazione che amministri le stanze.
Supponiamo inoltre che la tua applicazione funzioni su base client (inquilino).
Hai diversi clienti.
Quindi il tuo database conterrà una tabella per i clienti e una per le stanze.

Ora, ogni cliente ha N stanze.

Questo dovrebbe significare che hai una chiave esterna nella tabella della stanza, facendo riferimento alla tabella del cliente.

ALTER TABLE dbo.T_Room  WITH CHECK ADD  CONSTRAINT FK_T_Room_T_Client FOREIGN KEY(RM_CLI_ID)
REFERENCES dbo.T_Client (CLI_ID)
GO

Supponendo che un cliente passi ad altri software, dovrai cancellare i suoi dati nel tuo software. Ma se lo fai

DELETE FROM T_Client WHERE CLI_ID = x 

Quindi riceverai una violazione di chiave esterna, perché non puoi eliminare il client quando ha ancora stanze.

Ora avresti il ​​codice di scrittura nella tua applicazione che cancella le stanze del cliente prima che cancelli il client. Supponiamo inoltre che in futuro verranno aggiunte molte più dipendenze da chiavi esterne nel tuo database, poiché la funzionalità dell'applicazione si espande. Orribile. Per ogni modifica nel tuo database, dovrai adattare il codice dell'applicazione in N posti. Probabilmente dovrai adattare il codice anche ad altre applicazioni (ad es. Interfacce con altri sistemi).

C'è una soluzione migliore rispetto a farlo nel tuo codice.
Puoi semplicemente aggiungere ON DELETE CASCADE alla tua chiave esterna.

ALTER TABLE dbo.T_Room  -- WITH CHECK -- SQL-Server can specify WITH CHECK/WITH NOCHECK
ADD  CONSTRAINT FK_T_Room_T_Client FOREIGN KEY(RM_CLI_ID)
REFERENCES dbo.T_Client (CLI_ID) 
ON DELETE CASCADE 

Ora puoi dire

DELETE FROM T_Client WHERE CLI_ID = x 

e le stanze vengono cancellate automaticamente quando il client viene cancellato.
Problema risolto - senza modifiche al codice dell'applicazione.

Una parola di cautela: in Microsoft SQL-Server, questo non funzionerà se si dispone di una tabella che fa riferimento a se stessa. Quindi, se provi a definire una cascata di eliminazione su una struttura ad albero ricorsiva, in questo modo:

IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_T_FMS_Navigation_T_FMS_Navigation]') AND parent_object_id = OBJECT_ID(N'[dbo].[T_FMS_Navigation]'))
ALTER TABLE [dbo].[T_FMS_Navigation]  WITH CHECK ADD  CONSTRAINT [FK_T_FMS_Navigation_T_FMS_Navigation] FOREIGN KEY([NA_NA_UID])
REFERENCES [dbo].[T_FMS_Navigation] ([NA_UID]) 
ON DELETE CASCADE 
GO

IF  EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_T_FMS_Navigation_T_FMS_Navigation]') AND parent_object_id = OBJECT_ID(N'[dbo].[T_FMS_Navigation]'))
ALTER TABLE [dbo].[T_FMS_Navigation] CHECK CONSTRAINT [FK_T_FMS_Navigation_T_FMS_Navigation]
GO

non funzionerà, perché Microsoft-SQL-server non ti permette di impostare una chiave esterna con ON DELETE CASCADE su una struttura ad albero ricorsiva. Una ragione per questo è che l'albero è possibilmente ciclico e che potrebbe portare a una situazione di stallo.

D'altra parte, PostgreSQL può farlo;
il requisito è che l'albero non sia ciclico.
Se l'albero è ciclico, otterrai un errore di runtime.
In tal caso, dovrai solo implementare la funzione di cancellazione.

Una parola di cautela:
Questo significa che non puoi semplicemente cancellare e reinserire la tabella del client, perché se lo fai, cancellerà tutte le voci in "T_Room" ... (nessun aggiornamento non delta più)



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow