SQL Serverは0xと0x00を同じ値と見なしているようです:
SELECT CASE WHEN 0x = 0x00 THEN 1 ELSE 0 END
これは1
。
真のバイナリビットごとの比較動作を取得するにはどうすればよいですか?また、正確なルールとは、2つの(var)binary
値は等しいと見なされますか?
次の動作にも注意してください。
--prints just one of the values
SELECT DISTINCT [Data]
FROM (VALUES (0x), (0x00), (0x0000)) x([Data])
--prints the obvious length values 1, 2 and 3
SELECT DATALENGTH([Data]) AS [DATALENGTH], LEN([Data]) AS [LEN]
FROM (VALUES (0x), (0x00), (0x0000)) x([Data])
質問の背景は、バイナリデータを重複排除しようとしていることです。する必要がある GROUP BY
バイナリデータ。2つの値を比較するだけではありません。この問題に気付いてよかったです。
HASHBYTES
はLOBをサポートしないことに注意してください。もっと簡単な解決策も見つけたいです。
BOLのどこにも指定されているこの比較動作を見つけることができませんでした。
しかし、接続項目 右にゼロが埋め込まれたvarbinaryデータの無効な等値比較 は、
基本的に、標準では、[trailing]
00
のみが異なる文字列を等しいかそれ以下として処理する実装に任せています。私たちはそれを同じものとして扱います。
接続項目は、後続ゼロの存在がSQL Serverがバイトごとの比較動作と異なる唯一のケースであることも述べています。
末尾の0x00
文字のみが異なるSQL Serverの2つのバイナリ値を区別するために、質問に示されているように、比較にDATALENGTH
を追加することもできます。
ここでは、一般的にDATALENGTH
ではなくLEN
を優先する理由は、後者がvarchar
への暗黙のキャストを提供し、末尾のスペースに関する問題が発生するためです。
+-------------+--------------------+
| LEN(0x2020) | DATALENGTH(0x2020) |
+-------------+--------------------+
| 0 | 2 |
+-------------+--------------------+
どちらもあなたのユースケースで機能します。
興味深いことに、2つの値0x0と0x00は、同じ格納された値の単なる異なる文字表現です。次のスニペットを実行して、これを自分で証明してみてください。
DECLARE @foo sql_variant
, @bar sql_variant
, @bat sql_variant
SET @foo = 0x0
SET @bar = 0x00
SET @bat = 0x00000000
SELECT 'foo' AS 'Var', @foo AS 'Value'
, SQL_VARIANT_PROPERTY(@foo, 'BaseType') AS 'BaseType'
, SQL_VARIANT_PROPERTY(@foo, 'Precisionh') AS 'Precision'
, SQL_VARIANT_PROPERTY(@foo, 'Scale') AS 'Scale'
, SQL_VARIANT_PROPERTY(@foo, 'MaxLength') AS 'MaxLength'
UNION
SELECT 'bar' AS 'Var', @bar
, SQL_VARIANT_PROPERTY(@bar, 'BaseType')
, SQL_VARIANT_PROPERTY(@bar, 'Precisionh')
, SQL_VARIANT_PROPERTY(@bar, 'Scale')
, SQL_VARIANT_PROPERTY(@bar, 'MaxLength')
UNION
SELECT 'bat' AS 'Var', @bat
, SQL_VARIANT_PROPERTY(@bat, 'BaseType')
, SQL_VARIANT_PROPERTY(@bat, 'Precisionh')
, SQL_VARIANT_PROPERTY(@bat, 'Scale')
, SQL_VARIANT_PROPERTY(@bat, 'MaxLength')
SELECT
CASE
WHEN @foo = @bar
THEN 'equal'
ELSE 'NOT EQUAL'
END AS TestResults
ゼロパディングがなぜ人々を驚かせるのかは理解できますが、それは非常に長い間デフォルトの動作でしたので、私はそれを期待するようになったと思います。
-PatP