Czy istnieje sposób w T-SQL, aby rzutować nvarchar na int i zwrócić wartość domyślną lub NULL, jeśli konwersja się nie powiedzie?
116
Użyj funkcji TRY_CONVERT .
Utwórz funkcję zdefiniowaną przez użytkownika. Pozwoli to uniknąć problemów, o których wspomniał Fedor Hajdu w odniesieniu do waluty, liczb ułamkowych itp .:
CREATE FUNCTION dbo.TryConvertInt(@Value varchar(18))
RETURNS int
AS
BEGIN
SET @Value = REPLACE(@Value, ',', '')
IF ISNUMERIC(@Value + 'e0') = 0 RETURN NULL
IF ( CHARINDEX('.', @Value) > 0 AND CONVERT(bigint, PARSENAME(@Value, 1)) <> 0 ) RETURN NULL
DECLARE @I bigint =
CASE
WHEN CHARINDEX('.', @Value) > 0 THEN CONVERT(bigint, PARSENAME(@Value, 2))
ELSE CONVERT(bigint, @Value)
END
IF ABS(@I) > 2147483647 RETURN NULL
RETURN @I
END
GO
-- Testing
DECLARE @Test TABLE(Value nvarchar(50)) -- Result
INSERT INTO @Test SELECT '1234' -- 1234
INSERT INTO @Test SELECT '1,234' -- 1234
INSERT INTO @Test SELECT '1234.0' -- 1234
INSERT INTO @Test SELECT '-1234' -- -1234
INSERT INTO @Test SELECT '$1234' -- NULL
INSERT INTO @Test SELECT '1234e10' -- NULL
INSERT INTO @Test SELECT '1234 5678' -- NULL
INSERT INTO @Test SELECT '123-456' -- NULL
INSERT INTO @Test SELECT '1234.5' -- NULL
INSERT INTO @Test SELECT '123456789000000' -- NULL
INSERT INTO @Test SELECT 'N/A' -- NULL
SELECT Value, dbo.TryConvertInt(Value) FROM @Test
Odniesienie: Często korzystałem z tej strony podczas tworzenia mojego rozwiązania.
Tak :). Spróbuj tego:
ISNUMERIC()
ma kilka problemów wskazanych przez Fedora Hajdu .Zwraca true dla ciągów takich jak
$
(jest walutą),
lub.
(oba są separatorami)+
i-
.źródło
ISNUMERIC
tą odpowiedzią, aby w jakikolwiek sposób przydać się w przypadku niewalidowanych danych (i nie potrzebujeszISNUMERIC
sprawdzania w pierwszej kolejności dla poprawnie zweryfikowanych danych). Autor przyznaje, że istnieją te kwestie, ale ich nie rozwiązuje.TRY_CONVERT
/TRY_CAST
, które są wyraźnie przeznaczone do rozwiązania problemu OP. Ta odpowiedź została napisana przed wydaniem SQL 2012.Wolałbym raczej utworzyć funkcję taką jak TryParse lub użyć
TRY-CATCH
bloku T-SQL , aby uzyskać to, czego chcesz.ISNUMERIC nie zawsze działa zgodnie z przeznaczeniem. Podany wcześniej kod nie powiedzie się, jeśli:
SET @text = '$'
Znak $ można przekształcić w typ danych pieniądze, więc
ISNUMERIC()
w tym przypadku zwraca wartość true. To samo zrobi dla „-” (minus), „,„ (przecinek) i „.” postacie.źródło
ISNUMERIC()
Wraca1
również dla,
i.
.Jak już wspomniano, możesz napotkać kilka problemów, jeśli używasz
ISNUMERIC
:Jeśli chcesz niezawodnej konwersji, musisz samodzielnie ją zakodować.
Aktualizacja : Moim nowym zaleceniem byłoby użycie pośredniej konwersji testowej
FLOAT
do walidacji numeru. Podejście to opiera się na komentarzu Adrianm . Logikę można zdefiniować jako wbudowaną funkcję wartościowaną w tabeli:Niektóre testy:
Wyniki są podobne do odpowiedzi Josepha Sturtevanta , z następującymi głównymi różnicami:
.
lub,
w celu naśladowania ich zachowaniaINT
.'1,234'
i'1234.0'
wróćNULL
.'00000000000000001234'
ocenia do12
. Zwiększenie długości parametru spowodowałoby błędy w numerach, które się przepełniająBIGINT
, na przykład BBAN (podstawowe numery kont bankowych)'212110090000000235698741'
.Wycofane : poniższe podejście nie jest już zalecane, ponieważ zostało tylko w celach informacyjnych.
Poniższy fragment działa na nieujemnych liczbach całkowitych. Sprawdza, czy ciąg nie zawiera żadnych znaków niebędących cyframi, nie jest pusty i nie przepełnia (przez przekroczenie maksymalnej wartości dla
int
typu). Jednak podaje równieżNULL
prawidłowe liczby całkowite, których długość przekracza 10 znaków ze względu na zera wiodące.Jeśli chcesz obsługiwać dowolną liczbę wiodących zer, użyj poniższego. Zagnieżdżone
CASE
instrukcje, choć nieporęczne, są wymagane, aby promować ocenę zwarć i zmniejszyć prawdopodobieństwo błędów (wynikających na przykład z przekazania długości ujemnej doLEFT
).Jeśli chcesz obsługiwać dodatnie i ujemne liczby całkowite z dowolną liczbą wiodących zer:
źródło
Pozdrowienia.
Napisałem przydatną funkcję skalarną do symulacji funkcji TRY_CAST programu SQL SERVER 2012 w SQL Server 2008.
Możesz to zobaczyć w następnym linku poniżej i pomagamy sobie nawzajem w ulepszaniu go. Funkcja TRY_CAST dla SQL Server 2008 https://gist.github.com/jotapardo/800881eba8c5072eb8d99ce6eb74c8bb
Przykład:
Na razie obsługuje tylko typy danych INT, DATE, NUMERIC, BIT i FLOAT
Mam nadzieję, że uznasz to za przydatne.
KOD:
źródło
Odpowiedź Josepha wskazała, że ISNUMERIC również obsługuje notację naukową, taką jak „1.3e + 3”, ale jego odpowiedź nie obsługuje tego formatu liczb.
Rzutowanie na pieniądze lub float najpierw rozwiązuje problemy związane z walutą i nauką:
Funkcja nie powiedzie się, jeśli liczba jest większa niż bigint.
Jeśli chcesz zwrócić inną wartość domyślną, pozostaw tę funkcję, aby była ogólna, a następnie zamień wartość null:
źródło
Wiem, że to nie jest ładne, ale jest proste. Spróbuj tego:
źródło
Moim rozwiązaniem tego problemu było utworzenie funkcji pokazanej poniżej. Moje wymagania obejmowały, że liczba musi być standardową liczbą całkowitą, a nie BIGINT, i musiałem zezwolić na liczby ujemne i dodatnie. Nie znalazłem okoliczności, w których to się nie powiedzie.
źródło