CONVERT()のこの問題の原因は何ですか?


12

次の2つのステートメントを検討してください。

PRINT CONVERT(NUMERIC(38, 0), 0x0100000001, 0);
PRINT CONVERT(NUMERIC(38, 0), 0x0100010001, 0);

両方のステートメントが戻り-1ます。2番目のバイナリ値は最初の値よりも10進数65,536大きいため、これは間違っていませんか?

確かに、これは無言の切り捨てによるものではないでしょうか?

次のステートメントを実行した場合:

PRINT CONVERT(NUMERIC(38, 0),   0x00000001, 0);
PRINT CONVERT(NUMERIC(38, 0),   0x00010001, 0);

次のエラーが表示されます。

Msg 8114, Level 16, State 5, Line 1
Error converting data type varbinary to numeric.

ここで何が起こっているかを診断するにはどうすればよいですか?

これをSQL Server 2012 v11.0.5058で実行しています。結果は、SQL Server 2008 R2 SP2、SQL Server 2005、およびSQL Server 2000で同じです。


4
10進数と整数は、varbinaryで非常に異なる方法でエンコードされます。10進数にはより多くのスペースが必要です。試してくださいSELECT CONVERT(VARBINARY(32), 1), CONVERT(VARBINARY(32), 1.0);
アーロンバートランド

4
アーロンがスポットです。あなたの脳はバイナリデータを整数データに変換し、その後直接数値に変換していますが、SQL Serverはバイナリ->整数->数値(x、y)からの暗黙的な変換を行いません。SQL Serverが思考プロセスに従うには、次のような操作を行う必要がありますPRINT CONVERT(NUMERIC(38, 0), convert(int, 0x00000001), 0); PRINT CONVERT(NUMERIC(38, 0), convert(int, 0x00010001), 0);
トーマスストリンガー14

5
最初のバイトはスケール(0x01 = 1)、2番目のバイトは精度(0x00 = 0)、最後のバイトは値(0x01 = 1)です。バイト3と4が何のためにあるのかわかりません。記号はそこにありますが、2バイトは必要ありません。確かにそのビットを反転しても何も影響を受けていないようです。
マーティンスミス14

1
ありがとう、@ MartinSmith-いったいどうやって最初の2バイトがそのように使われていると判断したのですか?それは文書化されていますか?
マックスヴァーノン14

3
@AaronBertrand:それを答えたいですか?「未回答」リストからこれをマークできます。
すべての取引のジョン

回答:


2

10進数と整数は、varbinaryで非常に異なる方法でエンコードされます。10進数にはより多くのスペースが必要です。試してください:

SELECT CONVERT(VARBINARY(32), 1), CONVERT(VARBINARY(32), 1.0);

スペースを節約するために整数をvarbinaryとして保存するという究極の目標については、あなたはその質問に自分で答えたと思う-それは価値がない。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.