2010-01-25 5 views
2

J'ai décidé que j'utiliserais 8601 datetimes pour toutes les dates que je reviens de mon application. Soudain, dans un proc particulier, getdate() ne retourne pas un datetime avec un T au milieu. Je devrais aussi mentionner que je convertis l'ensemble contenant un datetime au format XML en utilisant FOR XML PATH. Généralement, lorsque je convertis une table contenant datetime en XML, je reçois 8601 dates formatées. Mais dans un cas, je ne le suis pas.pourquoi mon 126 datetime ne revient pas avec un T au milieu?

select (cast(getdate() as datetime)) -- returns 2010-01-25 10:13:46.033 

donc je convertis directement comme ceci:

select convert(datetime, getdate(), 126) -- returns 2010-01-25 10:14:35.923 

Mais si je l'ai jeté à un nvarchar je reçois le T !!

SELECT CONVERT(NVARCHAR(30), GETDATE(), 126) -- returns 2010-01-25T10:15:29.633 

Ce qui est encore inconnu pour moi est que si je sélectionne plusieurs versions de cela avec une union, la version T disparaît. Mais en sélectionnant sans union, la version T (la dernière) reste.

-- returns 4 rows of 2010-01-25 10:15:57.333 
select getdate() union all 
select (cast(getdate() as datetime)) union all 
select convert(datetime, getdate(), 126) union all 
SELECT CONVERT(NVARCHAR(30), GETDATE(), 126) 

Je n'ai aucune idée de ce qui pourrait se produire. Je pensais que 8601 dates étaient indépendantes des paramètres régionaux, donc je ne pense pas que ce soit quelque chose comme ça.

Référence ("aaaa-mm-jjThh: mi: SS.mmm" pour 126): http://msdn.microsoft.com/en-us/library/ms187928.aspx

Répondre

4

Vous confondez les valeurs datetime avec des chaînes formatées.

Les deux premiers exemples ne renvoient pas la date formatée du tout, c'est juste une valeur datetime. La façon dont la valeur est mise en forme dans le texte dépend de la façon dont vous affichez la valeur après l'avoir récupérée dans la base de données. Si vous habitez dans un autre pays et que vos paramètres de culture par défaut étaient différents, la date pourrait par exemple être affichée sous la forme 1/25/2010 10:14 AM.

Dans le deuxième exemple, le paramètre de format (126) est ignoré, car il n'y a pas de formatage ou d'analyse lors de la conversion d'une valeur datetime en valeur datetime.

Le troisième exemple met en forme la valeur datetime dans une chaîne avant qu'elle ne soit renvoyée à partir de la base de données, c'est pourquoi vous l'obtenez dans le format que la base de données utilise.

Si vous utilisez une union avec des types de données de différence, c'est le type precedence qui décide du type de résultat. Le type datetime a une priorité supérieure à nvarchar, il tente donc de convertir les valeurs nvarchar en datetime.

+0

Bien que (dans l'exemple d'union) si vous mettez la requête nvarchar en premier, il convertira tout en datetime .. bizarre .. (SQL Server 2005) –

+0

Je pense que vous avez raison, mon installation de test n'est pas bonne. Pourtant, je voyais l'étrangeté de mes résultats (pour le vrai proc). Le problème était dans le XML: si vous faites FOR XML PATH le convertisseur met en 8601 dates. J'ai édité la question pour inclure ceci. Dans mon cas, le problème était qu'il y avait un datalayer qui convertissait les datetimes différemment de SQL (parfois). – jcollum

+1

@Gaby: C'est correct. Ce n'est pas le premier résultat qui détermine le type de données, ce sont les règles de priorité de type. J'ai changé cela dans la réponse. – Guffa

1

Lorsque vous convertissez datetime, vous n'êtes pas choisir un format - la date, l'heure et datetime sont tous stockés dans un format interne. Ce n'est que lorsque vous convertissez en une chaîne (char, varchar, nvarchar) que le format est important pour la sortie. Dans les autres cas, le format est choisi par SQL Server implicitement, et il arrive à être proche mais pas identique à 8601.

+0

OK alors pourquoi certains de mes procs retourneraient-ils getdate() au format 8601 et d'autres dans le même format mais sans le T? Est-ce que getdate() ne devrait pas toujours retourner la même chose quel que soit le proc qui le renvoie? – jcollum

+0

getdate() ne retourne pas de chaîne, il renvoie un objet datetime. Lorsque l'objet datetime est converti en chaîne, le formatage a lieu. Si vous voulez que vos procs soient cohérents, demandez-leur de toujours retourner une chaîne. –

1

GETDATE() retourne déjà DATETIME, cette expression:

CONVERT(datetime, getdate(), 126) 

ne fait rien.

Vous pouvez remplacer toute autre option de format par omettre la partie CONVERT: le résultat sera le même.

La représentation sous forme de chaîne du DATETIME renvoyé est choisie par le client et non par le serveur.

Sa représentation interne est un nombre entier de 8 -Byte, avec les premiers 4 octets indiquant le nombre de jours à partir de 1900-01-01, et les deuxièmes 4 octets indiquant le nombre de secondes 1/300 de minuit.

Lorsque vous convertissez en NVARCHAR, le serveur crée la représentation textuelle et la renvoie telle quelle. Dans ce cas, vous voyez un T substitué par le serveur.

+0

Le problème ici est que dans certains procs, select getdate() revient au format 8601 et dans d'autres procs ce n'est pas le cas. – jcollum

+0

'GETDATE()' renvoie une séquence '8'-byte. Tout "retour" se produit uniquement lorsque la valeur est convertie en une chaîne (cela peut être fait par le client). – Quassnoi

+0

C'est bizarre que select getdate() revienne avec un T la semaine dernière, mais pas de T cette semaine. Je me demande comment diable cela aurait pu changer (quelque chose dans les réglages SSMS je suppose). – jcollum

0

priorité de l'opérateur, dans votre union, tout est converti en date et heure, puisqu'il s'agit de la première ligne.Si vous voulez le T alors vous avez besoin de transtyper en varchar mais encore une fois vous ne pouvez pas le faire dans une union puisque les types de données mélangés seront castés au même type de données (si possible)

Ceci inclut le T, un datetime lui-même est stockée sous forme de 2 entiers et n'a rien à voir avec ce

SELECT CONVERT(VARCHAR(30), GETDATE(), 126) 
Questions connexes