11

nvarchar(max)SQL Server 2014 を使用して、多くの K の ASCII テキスト ファイルを含むことができるという列を持つテーブルがあり[ASCII File]ます。次に、そのファイルで MD5 ハッシュバイトを実行したいのですが、結果のハッシュは常に 20 バイトである必要があります。

選択を行うと、hashbytes('MD5', [ASCII File])クエリがエラーで完了します

メッセージ 8152、レベル 16、状態 10、行 4
文字列またはバイナリ データが切り捨てられます。

しようとすると同じメッセージが表示されます

left(hashbytes('MD5', [ASCII File]), 50)

しようとすると同じメッセージが表示されます

convert(varchar(50), hashbytes('MD5', [ASCII File]))

hashbytes を実行している列がnvarchar(max)であるため、hashbytes 関数の結果も のようですnvarchar(max)

結果を予想される 20 の長さにする方法を教えてください。

4

4 に答える 4

15

私がハッシュバイトを実行しているフィールドは nvarchar(max) であるため、ハッシュバイトの結果は nvarchar(max) のようです。

いいえ、特にHASHBYTESの戻り値が a であるため、それは不可能ですVARBINARY。また、テストは単なる SELECT ステートメントであり、INSERT ステートメントではないため、戻り値で切り捨てエラーが発生することはありません。切り捨てエラーは、入力値から発生しています。リンクされた MSDN ページHASHBYTES(SQL Server 2012 および 2014 の場合) に記載されているとおり:

許可される入力値は 8000 バイトに制限されています。出力は、アルゴリズム標準に準拠しています。MD2、MD4、および MD5 の場合は 128 ビット (16 バイト)。SHA および SHA1 の場合は 160 ビット (20 バイト)。SHA2_256 の場合は 256 ビット (32 バイト)、SHA2_512 の場合は 512 ビット (64 バイト)。

つまり、入力は 8000 バイトに制限されており、出力は、指定されたアルゴリズムに基づいた固定バイト数です。

SQL Server 2016 の更新されたドキュメント (8000 バイトの制限が削除されました) には、次のように記載されています。

SQL Server 2014 以前の場合、許可される入力値は 8000 バイトに制限されています。

簡単なテストを実行できます。

DECLARE @Test NVARCHAR(MAX) = REPLICATE(CONVERT(NVARCHAR(MAX), N't'), 50000);
SELECT LEN(@Test);
SELECT HASHBYTES('MD5', @Test);

戻り値:

50000

Msg 8152, Level 16, State 10, Line 3
String or binary data would be truncated.

2016 より前のバージョンの SQL Server でハッシュ関数に 8000 バイトを超える値を渡す場合は、SQLCLR を使用する必要があります。独自の関数を作成するか、無料版のSQL# SQLCLR ライブラリ (私が作成したもの) をダウンロードしてインストールし、 Util_HashおよびUtil_HashBinary関数を使用することができます。

DECLARE @Test NVARCHAR(MAX) = REPLICATE(CONVERT(NVARCHAR(MAX), N't'), 50000);
SELECT LEN(@Test);
SELECT SQL#.Util_Hash('MD5', CONVERT(VARBINARY(MAX), @Test));
SELECT SQL#.Util_HashBinary('MD5', CONVERT(VARBINARY(MAX), @Test));

戻り値:

50000
40752EB301B41EEAEB309348CE9711D6
0x40752EB301B41EEAEB309348CE9711D6

アップデート

VARCHAR(MAX)8000 文字以下の列または変数 (または 4000 文字以下の列または変数)を使用する場合NVARCHAR(MAX)、問題はなく、すべてが期待どおりに機能します。

DECLARE @Test VARCHAR(MAX) = REPLICATE('t', 5000);
SELECT LEN(@Test) AS [Characters], 
       HASHBYTES('MD5', @Test) AS [MD5];

戻り値:

5000    0x6ABFBA10B49157F2EF8C85862B6E6313
于 2016-07-30T05:43:35.127 に答える