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).


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
*/

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.