SQL Server 2008 では、XML 属性に値 "0.01" があります。OPENXML を使用して、XML を一時テーブルに分割します。該当する列が実数型(単精度)の場合、表では0.01と出てきます。良い。ただし、精度が float (倍精度) の場合は、0.00999999977648258 となります。これは意味がありません。なぜこれを行うのですか?
次の質問は、値が一時テーブルでどのように表現されているかに関係なく、集計関数を実行すると、常に 0.00999999977648258 として返されるということです。これにより、検証エラーが発生しています。プロシージャは、入力が小さすぎる (< 0.01) と報告していますが、これは正しくありません。
これらの丸め誤差が発生する理由とそれらを克服する方法はありますか?
すでに試しました:列をvarcharにします。
EDIT2:
回答に基づいて、問題はIEEE数値が0.01を正確に表すことができないという事実によるものであることを理解しています。したがって、次の質問:
「WHERE {computed} < 0.01」、なぜその 0.01 もここで丸められないのですか? もしそうなら、式は予想通りに評価されます (つまり、0.00999999977648258 は < 0.00999999977648258 ではありません)。
編集:サンプルコードを表示
このコードはエラーを生成します。示されたフロートを実数に変更すると、エラーが「消えます」。少なくとも一時テーブルに関する限り。
DECLARE @XMLText varchar(max)
SET @XMLText =
'<query prodType="1">
<param type="1" lowMin="10" hiMax="300">
<item low="18" hi="20" mode="1" weight="1" />
<item low="220" hi="220" mode="0" weight="1" />
</param>
<param type="2" lowMin="4" hiMax="6">
<item low="5" hi="5" mode="1" weight="1" />
<item low="6" hi="6" mode="0" weight="0.01" />
</param>
<param type="3" lowMin="0" hiMax="300">
<item low="34" hi="34" mode="1" weight="0.75" />
<item low="40" hi="60" mode="1" weight="0.25" />
</param>
</query>'
DECLARE @hxml int, @sp INT, @StartXCount int
EXEC sp_xml_preparedocument @hxml OUTPUT, @XMLText
IF @sp != 0 BEGIN
SET @Result = '0'
RETURN
END
DECLARE @t table (
LowMin real,
HiMax real,
ParamTypeID int,
ParamWeight float, -- real <<<
Low real,
Hi real,
Mode tinyint
)
INSERT INTO @t
SELECT *
FROM OPENXML (@hxml, '/query/param/item', 2)
WITH (
LowMin real '../@lowMin',
HiMax real '../@hiMax',
ParamTypeID int '../@type',
ParamWeight real '@weight',
Low real '@low',
Hi real '@hi',
Mode tinyint '@mode'
)
SELECT * FROM @t