11

いくつかの不適切な形式のxml列に格納されている金額を抽出しようとしています(問題の一部であると思われるXML列にスキーマが定義されていません)。値が0のノードに遭遇すると、変換エラーが発生します。

例:

select xml.value('sum(/List/value)', 'numeric') sum
from (select cast('<List><value>1</value><value>2</value></List>' as xml) xml) a

合計3を与えます:

select xml.value('sum(/List/value)', 'numeric') sum
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a

「データ型nvarcharから数値への変換中にエラーが発生しました」というエラーが発生します。

ゼロ値のノードのリストを合計するときにクエリが0を返すようにする方法はありますか?

4

3 に答える 3

8

あなたのコメントは、あなたの問題に対する答えを示唆しています。

数値に変換する代わりに、float に変換します。指数表記は float に変換されます。

于 2009-05-11T14:17:08.333 に答える
4

整数に関する同様の問題を見ているときに、この質問に出くわし、最終的には答えになりました。最後の回答からの遅れにもかかわらず、将来他の誰かに役立つ場合に備えて、ここに追加します。

最初にあなたの基本的な答え:

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

XQuery では、値を標準の XML スキーマ型にキャストできます。これは、SQL Server によって正しく処理されます。

注意: SQL Server のデフォルトの「数値」には小数点以下の桁数がありません (位取りは「0」)。おそらく、次のようなことをするつもりでした:

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

(SQL Server に Xml から返された値から精度またはスケールを推測させることはできません。明示的に指定する必要があります)

double最後に、私が個人的に対処する必要がある実際の問題は、「0」値の xml 表現にも苦労している整数を扱っていたことを除いて、ほぼ同じでした。

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

更新:私が上に投稿した 10 進数処理ソリューション (SQL が値を解析する前に XQuery で 10 進数に変換する) の問題は、(想定/推測された) 浮動小数点 (double) データ型で集計が実際に行われることです。Xml に保存した値に高度な精度が必要な場合、実際にはこれを行うのは間違っている可能性があります。浮動小数点の集計により、実際にはデータが失われる可能性があります。EG ここでは、合計している数値の最後の桁を失います。

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

(「200000000000000000000000000」と出てきますが、これは間違っています)

この問題は、T-SQL で値を "float" として明示的に読み取るなど、ここで提供される他のアプローチにも同様に適用されます。

これを回避するために、集計操作の前にXQuery FLWOR 式を使用してデータ型を設定する最後のオプションを次に示します。この場合、集計は正しく行われ、正しい合計値が得られます (発生した場合は "0" 値も処理します)。

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

(「200000000000000000000000002」、正しい値になります)

于 2012-08-13T15:09:04.753 に答える
4

次のような and if ステートメントを使用することもできます。

@x.value('if (sum(/List/value) = 0) then 0 else sum(/List/value)', 'numeric')
于 2010-06-30T21:55:46.393 に答える