funkcja odbierania znaków i formatu daty powrotu (z niepoprawnym wprowadzeniem)

9

Muszę napisać funkcję, aby otrzymać znak ciągu i zwrócić format daty. Na przykład dane wejściowe to 20120101 i potrzebuję tego 01.01.2012. Problem polega na tym, że mogą występować nieprawidłowe dane, takie jak ten „2012ABCD”. W takim przypadku chcę, aby funkcja zwróciła ustaloną datę, na przykład 2020-01-01. Do tej pory napisałem:

Create Function ReturnDate
(@date varchar(8))

Returns date

  as

    begin
       declare @result date

          set @result = (select convert(date , @date,111))
                if(@@ROWCOUNT>0) return @result
                 else return '2020-01-01'
       return @result
    end

To nie działa i po prostu nie wiem, jak obsługiwać drugą część (gdy dane wejściowe są niepoprawne).

Pantea Tourang
źródło
1
Polecam przeczytanie „Kwerendy danych za pomocą języka Transact-SQL”. Jeśli będziesz dużo programować w języku SQL, ta książka nauczy Cię podstaw kodowania takich rzeczy. amazon.com/Exam-70-761-Querying-Data-Transact-SQL-ebook/dp/…
Tony Hinkle
1
Czy chcesz dokładnego analizowania yyyymmddformatu?
Dan Guzman

Odpowiedzi:

9

W SQL Server 2012 i późniejszych można użyć TRY_CONVERT, aby sprawdzić, czy dane wejściowe można przekonwertować. Jeśli nie jest to możliwe, zwracana jest wartość NULL, a następnie możesz wykonać WSPÓŁPRACĘ, aby uzyskać wartość przeliczoną lub ustaloną datę.

begin
   declare @result date
   set @result = COALESCE(TRY_CONVERT(date, @date, 111), '2012-01-01')
   return @result
end

Możesz także użyć TRY CATCHbloku i zwrócić ustaloną datę w CATCHbloku, ale najlepszym rozwiązaniem jest użycie TRY_CONVERT, aby SQL Server nie musiał obsługiwać błędu, ponieważ wymaga to więcej czasu i zasobów.

Funkcja dla tego typu kodu spowoduje większe obciążenie niż zwykłe użycie tej samej logiki w zapytaniu, więc jeśli jest wywoływana wiele razy na sekundę, możesz przeżuć znaczny zasób, używając dla niego funkcji. Rozumiem, że może to być wywołane z wielu fragmentów kodu, więc istnieje potrzeba, aby włączyć tę funkcję na wypadek, gdyby konieczna była zmiana domyślnej daty - wtedy nie ma zmian w skompilowanym kodzie i wystarczy zaktualizować tę funkcję.

Jeśli ten kod będzie często uruchamiany, należy rozważyć inne opcje, które zapewnią lepszą wydajność niż funkcja zdefiniowana przez użytkownika. Zapoznaj się z odpowiedzią Solomona, aby uzyskać przegląd dostępnych opcji i dodatkowe wyjaśnienie, dlaczego możesz wybrać jedną z nich.

Na przykład poniżej pokazano tę samą logikę zaimplementowaną jako wbudowana funkcja o wartościach w tabeli, która musi być używana z, CROSS APPLYjeśli nie jest dostarczana z wartością statyczną, ale działa znacznie lepiej niż skalarny UDF:

USE [tempdb];

GO
CREATE
OR ALTER -- comment out if using pre-SQL Server 2016 SP1
FUNCTION dbo.ReturnDate (@Date VARCHAR(8))
RETURNS TABLE
AS RETURN
  SELECT ISNULL(TRY_CONVERT(DATE, @Date, 111), '2020-01-01') AS [TheDate];
GO


SELECT *
FROM   (VALUES (1, '20120101'), (2, '2012ABCD')) tab(ID, Input)
CROSS APPLY dbo.ReturnDate(tab.[Input]) dt
/*
ID    Input       TheDate
1     20120101    2012-01-01
2     2012ABCD    2020-01-01
*/
Tony Hinkle
źródło
6
Ale po prostu użyłbym TRY_CONVERT w zapytaniu i odrzuciłbym cały pomysł użycia nieefektywnego skalarnego UDF do tego ...
Aaron Bertrand
2
Naprawdę nie dbam o punkty powtórzeń, więc nie mówię tego z powodu utraty takich punktów, ale społeczność nie korzysta z odrzucenia oczywiście poprawnej odpowiedzi. Zamiast głosować w dół, napisz odpowiedź, edytuj mój lub zostaw komentarz na temat tego, co należy zmienić. OP poprosił o funkcję i zdaję sobie sprawę, że to może nie być najlepsze rozwiązanie, ale o to poprosiliśmy.
Tony Hinkle,
3
Tony: Nie głosowałem za odrzuceniem, ale z pewnością zgadzam się, że ktoś nie powinien głosować za odrzuceniem bez podania uzasadnienia w komentarzu lub podniesienia głosu w istniejącym komentarzu, który zawiera ich uzasadnienie. To powiedziawszy: 1) nie ma FINALLYbloku w T-SQL (myślę, że miałeś na myśli CATCH). 2) prawdopodobnie powinieneś wspomnieć, że TRY_CONVERTzaczął się w 2012 roku (niektórzy ludzie utknęli przed SQL Server 2012). 3) Czy rozważałeś Inline TVF? Nie mają one takich samych problemów z wydajnością jak Skalarne UDF.
Solomon Rutzky
1
@TonyHinkle Dzięki za dokonanie tych zmian i odniesienie do mojej SO odpowiedzi :). Nadal nie jestem pewien, ilu czytelników będzie w stanie zrobić skok, widząc logikę UDF i czytając, że wbudowany TVF będzie lepszy, do pomyślnego wdrożenia iTVF. Więc poszedłem naprzód i dodałem go na końcu twojej odpowiedzi.
Solomon Rutzky
1
@SolomonRutzky Thanks. Tak naprawdę nie jestem programistą SQL, więc wciąż mam nad sobą głowę. Może nie powinienem odpowiadać na coś takiego, ale jest to ogromna szansa na naukę.
Tony Hinkle