2016-04-13 14 views
5

Podczas budowania procedury składowanej, która wstawia do prostej tabeli łącza, powinna sprawdzić, czy istnieją FK i zwracać błąd z wdziękiem lub po prostu pozwolić SQL rzucić wyjątek?Dobra praktyka zachowana w procedurze przechowywania? Czy powinni sprawdzić, czy klucze obce istnieją przed wstawieniem?

  • Co to jest najlepsza praktyka?
  • Co jest najbardziej wydajne?

Tylko w przypadku, gdy ktoś nie rozumie moje pytanie:

  • Table A
  • Table B
  • Table AB

powinienem zrobić:

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 

lub

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

i niech SQL wyjątek

Dzięki

+0

Jeśli martwisz się wydajnością i spodziewasz się wielu naruszeń klucza zagranicznego, zajrzyj na temat [Wpływ różnych technik obsługi błędów na wydajność] (http://sqlperformance.com/2012/08/t-sql-queries/obsługa błędów) i zmierzyć wpływ na swoją bazę danych i sprzęt. –

Odpowiedz

2

Jeśli tabele są pod kontrolą, nie ma powodu, aby przeprowadzić dodatkową kontrolę. Załóżmy, że są poprawnie skonfigurowane i pozwalają SQL obsługiwać dowolny błąd. Ciągłe sprawdzanie, czy rzeczywiście zrobiłeś to, co zamierzałeś zrobić, to zbyt defensywne programowanie, które dodaje niepotrzebnego skomplikowania do twojego kodu.

Na przykład nie byłoby napisać kod tak:

i = 1; 

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

I zobaczyć tę sytuację jako podobne.

Jeśli tabele nie są pod Twoją kontrolą, może być użyteczne z wdziękiem obsługiwać błąd. Na przykład, jeśli ta procedura może zostać uruchomiona na dowolnym zestawie tabel utworzonym przez użytkownika lub jeśli zostanie udostępniona użytkownikom zewnętrznym, którzy są zobowiązani do skonfigurowania tabel we własnej bazie danych, może być konieczne dodanie niestandardowego błędu obsługa. Celem tego byłoby podanie użytkownikowi dokładniejszego opisu, co poszło nie tak.

0

Zazwyczaj sprawdzam Fk. Jeśli Fk nie istnieje, a następnie wyrzuć błąd przyjazny, a instrukcja insert nie zostanie wykonana, baza danych również nie zablokuje tabeli.

+0

To powinien być komentarz. Brak odpowiedzi –

2

Podstawową koncepcją jest sprawdzanie poprawności wartości przed kodem generującym potencjalnie błąd. Jednak w tym przypadku może istnieć (przynajmniej teoretycznie) zmiana w tabeli a lub tabeli b między sprawdzeniami istniejącymi a instrukcją wstawiania, która spowodowałaby błąd naruszenia fk.

chciałbym zrobić coś takiego:

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

Funkcja ERROR_MESSAGE() zwraca błąd, który został rasied w bloku try.

Następnie w kodzie wykonawczym można po prostu sprawdzić, czy zwrócony komunikat o błędzie jest pusty.Jeśli tak, to wiesz, że insert się powiódł. Jeśli nie, poradzisz sobie z tym wyjątkiem, jakkolwiek uważasz, że pasuje.

+0

Przesada, chyba że masz uzasadniony powód przypuszczać, że ktoś inny może zmieniać tabele podczas działania kodu. –

+0

I tak będziesz musiał poradzić sobie z błędem, dlaczego nie zachować go na serwerze sql? To nie jest bardziej przesadny w porównaniu do obsługi błędu w kodzie klienta. –

+0

Bez względu na to, co robisz, kod klienta będzie musiał obsługiwać ogólny błąd SQL, który jest zgłaszany podczas wywoływania procedury. Tak więc obsługa tego błędu specjalnie dodaje coś dodatkowego do twojego kodu - i będziesz musiał dodać dodatkową obsługę tego błędu po stronie klienta, jak również, aby robiło to jakąkolwiek różnicę. Jeśli nie masz faktycznego powodu, aby uważać, że tabele mogą być ustawione nieprawidłowo (np. Są poza twoją kontrolą), ten rodzaj obsługi błędów jest moim zdaniem zbyt defensywny. –