je suis tombé sur cette question, et finalement une réponse, tout en regardant un problème similaire avec des nombres entiers. Malgré le retard depuis la dernière réponse, j'ajoute ici au cas où cela aiderait quelqu'un d'autre à l'avenir.
Première votre réponse de base:
select xml.value('xs:decimal(sum(/List/value))', 'numeric') sum
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a
En XQuery vous pouvez jeter la valeur à un standard XML type de schéma, qui sera ensuite traitée correctement par SQL Server. S'il vous plaît noter: le "numérique" par défaut dans SQL Server n'a pas de décimales (échelle de "0")! Vous avez sans doute l'intention de faire quelque chose comme:
select xml.value('xs:decimal(sum(/List/value))', 'numeric(20,5))') sum
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a
(vous ne pouvez pas obtenir SQL Server pour déduire la précision ou l'échelle de la valeur renvoyée par la Xml, vous devez spécifier explicitement)
Enfin, le réel question que je personnellement besoin d'adresse était presque exactement la même chose, sauf que je traitais avec des nombres entiers, qui supportent mal les représentation XML de « 0 » double
valeurs:
select xml.value('xs:int(sum(/List/value))', 'int') sum
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a
MISE à JOUR: Le problème avec la solution de gestion des décimales que j'ai posté plus haut (conversion en décimal dans XQuery avant que SQL ne parvienne à analyser la valeur) est que l'agrégation se produit avec le type de données (supposé/inféré) à virgule flottante (double). Si les valeurs que vous avez stockées dans votre XML requièrent un haut degré de précision, cela peut être une mauvaise chose à faire - l'agrégation à virgule flottante peut en fait entraîner une perte de données. EG ici, nous perdons le dernier chiffre du numéro nous sommateur:
select xml.value('xs:decimal(sum(/List/value))', 'numeric(28, 0)') sum
from (select cast('<List>
<value>1000000000000000000000000001</value>
<value>1000000000000000000000000001</value>
</List>' as xml) xml) a
(sort à « 2000000000000000000000000000 », ce qui est faux)
Cette question vaut également pour d'autres approches proposées ici, comme explicitement lire la valeur "float" dans T-SQL.
Pour éviter cela, voici une dernière option utilisant une expression XQuery FLWOR pour définir le type de données avant l'opération d'agrégation. Dans ce cas, l'agrégation se produit correctement, et nous avons la valeur additionnée correcte (tout en traitant également « 0 » valeurs si/quand ils se produisent):
select xml.value('sum(for $r in /List/value return xs:decimal($r))', 'numeric(28, 0)') sum
from (select cast('<List>
<value>1000000000000000000000000001</value>
<value>1000000000000000000000000001</value>
</List>' as xml) xml) a
(SORT à « 2000000000000000000000000002 », la valeur correcte)
Il semble que sum (/ List/value) renvoie un flottant "0.0E0" lorsque la somme est nulle et que ce nombre ne peut pas être converti en numérique. Une idée de pourquoi je vois ce comportement? –