2016-04-13 11 views
5

Quando si crea una stored procedure che si inserisce in una tabella di collegamento semplice, dovrebbe controllare se esistono i FK e restituire con garbo un errore o semplicemente lasciare che SQL lanci un'eccezione?Procedura consigliata per la procedura memorizzata? Dovrebbero controllare se esistono chiavi esterne prima di inserire?

  • Qual è la migliore pratica?
  • Cosa è più efficiente?

Solo nel caso qualcuno non capisce la mia domanda:

  • Table A
  • Table B
  • Table AB

devo fare:

IF EXISTS(SELECT 1 FROM A WHERE Id = @A) AND EXISTS(SELECT 1 FROM B WHERE Id = @B) 
BEGIN 
     INSERT AB (AId,BId) VALUES (@A, @B) 
END 
ELSE 
    --handle gracefully, return error code or something 

o

INSERT AB (AId,BId) VALUES (@A, @B) 

e lasciare SQL un'eccezione

Grazie

+0

Se si è preoccupati per le prestazioni e si prevedono molte violazioni delle chiavi esterne, consultare [Impatto sulle prestazioni delle diverse tecniche di gestione degli errori] (http://sqlperformance.com/2012/08/t-sql-queries/gestione degli errori) e misurare l'impatto sul proprio database e hardware. –

risposta

2

Se le tabelle sono sotto il vostro controllo, non v'è alcun motivo per eseguire un controllo supplementare. Si supponga di essere impostati correttamente e che SQL gestisca qualsiasi errore. Controllare costantemente di aver effettivamente fatto ciò che intendevi fare è una programmazione eccessivamente difensiva che aggiunge complessità non necessaria al tuo codice.

Ad esempio, non è necessario scrivere codice come questo:

i = 1; 

if (i != 1) 
{ 
    print "Error: i is not 1!"; 
} 

E vedere questa situazione come simile.

Se i tavoli non sono sotto il vostro controllo può essere utile gestire l'errore con garbo. Ad esempio, se questa procedura può essere eseguita su un insieme arbitrario di tabelle create dall'utente, o se verrà distribuita agli utenti esterni che sono obbligati a impostare le tabelle nel proprio database, è possibile aggiungere un errore personalizzato la manipolazione. Lo scopo di questo sarebbe dare all'utente una descrizione più chiara di cosa è andato storto.

0

Di solito controllerò Fk. Se Fk non esiste, quindi genera un errore, e l'istruzione di inserimento non verrà eseguita, anche il database non bloccherà la tabella.

+0

Questo dovrebbe essere un commento. Non è una risposta –

2

Come concetto di base, la convalida dei valori prima di un potenziale codice di errore è una buona cosa. Tuttavia, in questo caso, potrebbe esserci (almeno in teoria) una modifica nella tabella a o nella tabella b tra i controlli di esistenza e l'istruzione di inserimento, che aumenterebbe l'errore di violazione di fk.

vorrei fare qualcosa di simile:

BEGIN TRY 
    INSERT AB (AId,BId) VALUES (@A, @B) 
    SELECT NULL As ErrorMessage 
END TRY 
BEGIN CATCH 
    SELECT ERROR_MESSAGE() AS ErrorMessage 
END CATCH 

La funzione ERROR_MESSAGE() restituisce l'errore che è stato rasied nel blocco try.

Quindi nel codice di esecuzione è possibile controllare semplicemente se il messaggio di errore restituito è nullo.Se lo è, sai che l'inserimento ha avuto successo. Altrimenti, puoi gestire questa eccezione come ritieni opportuno.

+0

Overkill a meno che non ci sia un motivo valido per credere che qualcun altro stia cambiando le tabelle durante l'esecuzione del codice. –

+0

Dovrai comunque gestire l'errore, perché non tenerlo nel server sql? Non è più un overkill a confronto per gestire l'errore nel codice client. –

+0

Indipendentemente da ciò che si fa, il codice client dovrà gestire il caso generico di errore SQL durante il richiamo della procedura. Quindi gestire questo errore in particolare aggiunge qualcosa in più al tuo codice - e dovresti aggiungere una maneggevolezza aggiuntiva di questo errore anche dal lato client per fare la differenza. A meno che tu non abbia un motivo valido per pensare che le tabelle potrebbero essere impostate in modo errato (ad es. Sono fuori dal tuo controllo), a mio parere questo tipo di gestione degli errori è eccessivamente difensivo. –

Problemi correlati