Piszę funkcję zdefiniowaną przez użytkownika w SQL Server 2008. Wiem, że funkcje nie mogą generować błędów w zwykły sposób - jeśli spróbujesz dołączyć instrukcję RAISERROR SQL zwraca:
Msg 443, Level 16, State 14, Procedure ..., Line ...
Invalid use of a side-effecting operator 'RAISERROR' within a function.
Ale faktem jest, że funkcja pobiera dane wejściowe, które mogą być nieprawidłowe, a jeśli tak, to nie ma żadnej znaczącej wartości, którą funkcja może zwrócić. Co mam wtedy zrobić?
Mógłbym oczywiście zwrócić wartość NULL, ale każdemu deweloperowi, który użyłby tej funkcji, byłoby trudne do rozwiązania tego problemu. Mógłbym też spowodować dzielenie przez zero lub coś w tym rodzaju - wygenerowałoby to komunikat o błędzie, ale wprowadzający w błąd. Czy jest jakiś sposób, żebym mógł w jakiś sposób zgłosić swój własny komunikat o błędzie?
declare @error int; set @error = 'Error happened here.';
Zwykłą sztuczką jest wymuszenie dzielenia przez 0. Spowoduje to zgłoszenie błędu i przerwanie bieżącej instrukcji oceniającej funkcję. Jeśli programista lub osoba z pomocy technicznej wie o takim zachowaniu, zbadanie i rozwiązanie problemu jest dość łatwe, ponieważ dzielenie przez błąd 0 jest rozumiane jako objaw innego, niezwiązanego z nim problemu.
Choć wygląda to źle z dowolnego punktu widzenia, niestety projekt funkcji SQL w tej chwili nie pozwala na lepszy wybór. Używanie RAISERROR powinno być absolutnie dozwolone w funkcjach.
źródło
Idąc za odpowiedzią Vladimira Koroleva, idiomem warunkowego rzucania błędu jest
źródło
Myślę, że najczystszym sposobem jest po prostu zaakceptowanie, że funkcja może zwrócić wartość NULL, jeśli zostaną przekazane nieprawidłowe argumenty. Jeśli jest to jasno udokumentowane, to powinno być w porządku?
źródło
RAISEERROR
lub@@ERROR
nie są dozwolone w UDF. Czy można przekształcić UDF w procedurę strated?Z artykułu Erlanda Sommarskoga Obsługa błędów w SQL Server - tło :
źródło
Najlepsza odpowiedź jest ogólnie najlepsza, ale nie działa w przypadku funkcji wartościowanych w tabeli wbudowanej.
MikeTeeVee podał rozwiązanie tego problemu w swoim komentarzu do górnej odpowiedzi, ale wymagało to użycia funkcji agregującej, takiej jak MAX, która nie działała dobrze w moich okolicznościach.
Bawiłem się alternatywnym rozwiązaniem w przypadku, gdy potrzebujesz pliku udf o wartości tabeli wbudowanej, który zwraca coś w rodzaju select * zamiast agregatu. Przykładowy kod rozwiązujący ten konkretny przypadek znajduje się poniżej. Jak już ktoś wskazał ... "JEEZ wotta hack" :) Z zadowoleniem przyjmuję lepsze rozwiązanie w tej sprawie!
źródło
Kilku ludzi pytało o zgłaszanie błędów w funkcjach z wartościami tabelarycznymi, ponieważ nie można używać rzeczy typu „ RETURN [nieprawidłowe rzutowanie] ”. Przypisanie nieprawidłowego rzutowania do zmiennej działa równie dobrze.
To skutkuje:
źródło
Nie mogę komentować odpowiedzi davec na temat funkcji wycenianej w tabeli, ale moim skromnym zdaniem jest to łatwiejsze rozwiązanie:
źródło
Jednym ze sposobów (hack) jest posiadanie funkcji / procedury składowanej, która wykonuje nieprawidłową akcję. Na przykład następujący pseudo SQL
Gdzie w tabeli tbl_throw_error istnieje unikalne ograniczenie w kolumnie err_msg. Efektem ubocznym tego (przynajmniej w MySQL) jest to, że wartość err_msg jest używana jako opis wyjątku, gdy wraca on do obiektu wyjątku na poziomie aplikacji.
Nie wiem, czy możesz zrobić coś podobnego z SQL Server, ale warto spróbować.
źródło