natknąłem to pytanie, a ostatecznie odpowiedź, patrząc na podobny problem z całkowitymi. Pomimo opóźnienia od ostatniej odpowiedzi, dodam tutaj, na wypadek gdyby pomógł komukolwiek innemu w przyszłości.
Pierwszy podstawowy odpowiedź:
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
W XQuery można oddać wartość do standardowego typu XML Schema, które następnie będą prawidłowo obsługiwane przez SQL Server.
UWAGA: domyślny "numeryczny" w Serwerze SQL nie ma żadnych miejsc dziesiętnych (skala "0")! Prawdopodobnie zamierzał zrobić coś więcej takich jak:
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
(nie można uzyskać SQL Server wywnioskować precyzji lub skali od wartości zwracanej z XML, należy wyraźnie określić ją)
Wreszcie rzeczywisty problem, który ja osobiście potrzebne do adresu była niemal dokładnie takie same, z wyjątkiem miałem do czynienia z liczbami całkowitymi, które również borykają się z reprezentacją xml „0” double
wartości:
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
UPDATE: Problem z rozwiązaniem do obsługi dziesiętnej, które napisałem powyżej (konwersja na wartość dziesiętną w XQuery, zanim SQL zacznie analizować wartość), jest taka, że agregacja zachodzi w rzeczywistości z (założonym/wnioskiem) typem danych zmiennoprzecinkowych (double). Jeśli wartości, które zapisałeś w swoim Xml, wymagają dużej precyzji, może to być niewłaściwe - agregacja zmiennoprzecinkowa może w rzeczywistości spowodować utratę danych. EG tutaj tracimy ostatnią cyfrę numeru jesteśmy podsumowującej:
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
(wychodzi do „2000000000000000000000000000”, co jest źle)
Problem ten dotyczy w równym stopniu do innych rozwiązań oferowanych tutaj, jak wyraźnie odczytanie wartości jako "float" w T-SQL.
Aby tego uniknąć, oto ostatnia opcja przy użyciu wyrażenia XQuery FLWOR, aby ustawić typ danych przed operacją agregacji przed. W tym przypadku, agregacja zachodzi poprawnie i mamy prawidłowy zsumowane wartości (a także przenoszenia wartości „0” jeśli/kiedy występują):
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
(wychodzi „2000000000000000000000000002”, prawidłowa wartość)
Wygląda na to, że suma (/ Lista/wartość) zwraca wartość "0,0E0", gdy suma wynosi zero i tej liczby nie można przekonwertować na wartość liczbową. Jakiś pomysł, dlaczego widzę to zachowanie? –