5

Dans la tradition de this question et à la lumière de the documentation, comment peut-on faire cette fonction déterministe:Comment rendre les conversions de varchar à datetime déterministe?

ALTER FUNCTION [udf_DateTimeFromDataDtID] 
(
    @DATA_DT_ID int -- In form YYYYMMDD 
) 
RETURNS datetime 
WITH SCHEMABINDING 
AS 
BEGIN 
    RETURN CONVERT(datetime, CONVERT(varchar, @DATA_DT_ID)) 
END 

Ou celui-ci (à cause des littéraux chaîne/date - et oui, j'ai aussi essayé « 1900 -01-01'):

ALTER FUNCTION udf_CappedDate 
(
    @DateTimeIn datetime 
) 
RETURNS datetime 
WITH SCHEMABINDING 
AS 
BEGIN 
    IF @DateTimeIn < '1/1/1900' 
     RETURN '1/1/1900' 
    ELSE IF @DateTimeIn > '1/1/2100' 
     RETURN '1/1/2100' 

    RETURN @DateTimeIn 
END 

Répondre

6

BOL dit que CONVERTest déterministe avec datetimes si le style paramètre est spécifié. Donc, si vous changez la première UDF à:

RETURN CONVERT(datetime, CONVERT(varchar, @DATA_DT_ID), 112) 

Ensuite, il devrait être déterministe, si je comprends bien les documents correctement.

On peut supposer que la même astuce pourrait être utilisé dans votre deuxième UDF:

IF @DateTimeIn < CONVERT(datetime, '1/1/1900', 101) 
    RETURN CONVERT(datetime, '1/1/1900', 101) 

Je vraiment souhait qu'il y avait un moyen de spécifier littéraux datetime dans T-SQL.

EDIT:

Comme indiqué par Arvo dans les commentaires (merci, Arvo), le format littéral d'horodatage ODBC peut être utilisé (même lorsque vous utilisez OLE DB) de sorte que la seconde fonction ci-dessus peut être mieux écrit comme:

IF @DateTimeIn < {d '1900-01-01'} 
    RETURN {d '1900-01-01'} 
...etc. 

et la conversion en date/heure est effectuée au moment de la compilation au lieu de l'heure d'exécution. Notez que le format de la date doit être très précis (voir Arvo's link to the datetime data type):

  d         aaaa-mm-jj
  t         hh: mm: ss [.fff ]
ts         aaaa-mm-jj hh: mm: ss [.fff]

+0

J'ai seulement utilisé le style lors de la conversion de TO varchar - la documentation est un peu ambiguë, mais je l'ai essayé et cela fonctionne clairement. –

+0

@P Papa, Amen sur les littéraux datetime. –

+2

A propos des littéraux datetime: ne pouvez-vous pas utiliser le format d'horodatage ODBC comme {d '1990-10-02'}? À partir de http://msdn.microsoft.com/en-us/library/ms187819.aspx: Les applications qui utilisent les API ADO, OLE DB et ODBC peuvent utiliser ce format timestamp ODBC pour représenter les dates et les heures. – Arvo

2

a partir des articles que vous Linked:

déterministe, le paramètre de style doit être une constante. De plus, les styles inférieurs ou égaux à 100 sont non déterministes, à l'exception des styles 20 et 21. Styles supérieurs à 100 sont déterministes, à l'exception des styles 106, 107, 109 et 113.

Vous devez utiliser un paramètre de style dans vos conversions à datetime.

Par exemple:

CONVERT(datetime, '2008-01-01', 121) 

Sauf ne pas utiliser 121 ...

+0

Donc, aucune date littérale sous forme de chaînes dans les fonctions UDF sans être convertie? –

+0

Si les chaînes sont converties implicitement en dates, ces conversions manquent de styles "constants" et rendront la fonction non déterministe. –