funzione per ricevere un input di caratteri e un formato di data di ritorno (con input errato)


9

Devo scrivere una funzione per ricevere un carattere stringa e restituire il formato data. Ad esempio, l'ingresso è 20120101 e ho bisogno di questo 01-01-2012. Il problema è che potrebbero esserci degli input errati come questo "2012ABCD". In tal caso, desidero che la funzione restituisca una data fissa come 2020-01-01. Quello che ho scritto finora è:

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

Questo non funziona e non so come gestire la seconda parte (quando l'input è errato).


1
Potrei consigliarti di leggere "Richiesta di dati con Transact-SQL" Se eseguirai molta programmazione SQL, questo libro ti insegnerà le basi di come codificare cose come questa. amazon.com/Exam-70-761-Querying-Data-Transact-SQL-ebook/dp/…
Tony Hinkle

1
Vuoi un'analisi rigorosa del yyyymmddformato?
Dan Guzman,

Risposte:


9

Su SQL Server 2012 e versioni successive è possibile utilizzare TRY_CONVERT per verificare se è possibile convertire l'input. In caso contrario, viene restituito un valore NULL, quindi è possibile eseguire una COALESCE per ottenere il valore convertito o la data fissa.

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

È inoltre possibile utilizzare un TRY CATCHblocco e restituire la data fissa nel CATCHblocco, ma è consigliabile utilizzare TRY_CONVERT in modo che SQL Server non debba gestire un errore poiché richiede più tempo e risorse.

Una funzione per questo tipo di codice comporterà un sovraccarico maggiore del semplice utilizzo della stessa logica nella query, quindi se viene chiamata più volte al secondo, è possibile masticare risorse significative utilizzando una funzione per esso. Capisco che questo può essere chiamato da numerosi pezzi di codice, quindi c'è il desiderio di renderlo una funzione nel caso in cui la data predefinita debba essere cambiata - quindi non si tratta di modifiche al codice compilate e basta aggiornare questa funzione.

Se questo codice verrà eseguito molto, è necessario considerare altre opzioni che forniranno prestazioni migliori rispetto a una funzione definita dall'utente. Perfavore guarda la risposta di Solomon per una panoramica delle tue opzioni e un'ulteriore spiegazione del perché potresti scegliere l'una rispetto all'altra.

Ad esempio, quanto segue mostra la stessa logica implementata come funzione inline con valori di tabella, che deve essere utilizzata CROSS APPLYse non fornita con un valore statico, ma offre prestazioni molto migliori di un UDF scalare:

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
Ma vorrei solo usare TRY_CONVERT nella query e scartare l'idea di utilizzare un UDF scalare inefficiente per questo ...
Aaron Bertrand

2
Non mi interessa davvero i punti di riferimento, quindi non lo dico a causa della perdita di tali, ma la comunità non beneficia del downvoting di una risposta ovviamente corretta. Invece di effettuare il downgrade, scrivi una risposta, modifica la mia o lascia un commento su ciò che deve essere cambiato. OP ha chiesto una funzione e mi rendo conto che potrebbe non essere la soluzione migliore, ma è la soluzione che è stata richiesta.
Tony Hinkle,

3
Tony: Non ho votato in negativo, ma sono certamente d'accordo sul fatto che qualcuno non debba votare in negativo senza fornire il ragionamento in un commento o votare in eccesso un commento esistente che include il proprio ragionamento. Detto questo: 1) non c'è nessun FINALLYblocco in T-SQL (penso che tu intendessi CATCH). 2) dovresti probabilmente menzionare che è TRY_CONVERTiniziato nel 2012 (alcune persone sono bloccate prima di SQL Server 2012). 3) hai considerato un TVF in linea? Quelli non hanno gli stessi problemi di prestazioni degli UDF scalari.
Solomon Rutzky,

1
@TonyHinkle Grazie per aver apportato queste modifiche e per il riferimento alla mia risposta SO :). Tuttavia, non sono sicuro di quanti lettori saranno in grado di fare il salto dal vedere la logica UDF e leggere che un TVF in linea sarà migliore, per implementare con successo iTVF. Quindi, sono andato avanti e l'ho aggiunto alla fine della tua risposta.
Solomon Rutzky,

1
@SolomonRutzky Grazie. Non sono davvero uno sviluppatore SQL, quindi è ancora sopra la mia testa. Forse non dovrei rispondere a una cosa del genere, ma è un'enorme opportunità di apprendimento.
Tony Hinkle,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.