如何确保Microsoft SQL Server中的特定字符编码?

时间:2017-07-21 19:37:13

标签: sql-server encoding

我需要确保字符串以已知的字符编码进行编码。到目前为止,我对MS SQL Server的研究和测试表明,所记录的编码是'UCS-2',但实际编码(在服务器上)是'UCS-2LE'。

这似乎不太可靠。我喜欢的是PERL,Node或大多数内容中的ENCODE函数,因此无论升级或设置更改如何,我的哈希函数都将处理已知输入。

我们可以将散列字符串限制为HEX,因此在最坏的情况下,我们可以手动将16个可能的输入字符映射到正确的字节。有人对此提出建议吗?

这是我正在使用的PERL:

use Digest::SHA qw/sha256/;
use Encode qw/encode/;

$seed = 'DDFF5D36-F14D-495D-BAA6-3688786D6CFA';
$string = '123456789';

$target = '57392CD6A5192B6185C5999EB23D240BB7CEFD26E377D904F6FEF262ED176F97';

$encoded = encode('UCS-2LE', $seed.$string);
$sha256 = uc(unpack("H*", sha256($encoded)));

print "$target\n$sha256\n";

哪个匹配MS SQL:

HASHBYTES('SHA_256', 'DDFF5D36-F14D-495D-BAA6-3688786D6CFA123456789')

但我真正想要的是:

HASHBYTES('SHA_256', ENCODE('UCS2-LE', 'DDFF5D36-F14D-495D-BAA6-3688786D6CFA123456789'))

因此,无论MS SQL将输入字符串编码为什么,HASHBYTES将始终在已知的字节数组上运行。

1 个答案:

答案 0 :(得分:0)

SQL Server仅对声明为nvarchar的列,变量和文字使用UCS-2。在所有其他情况下,它使用8位ASCII和当前数据库的编码,除非另有说明(例如,使用collate子句)。

因此,您必须指定Unicode文字:

select HASHBYTES('SHA_256', N'DDFF5D36-F14D-495D-BAA6-3688786D6CFA123456789');

或者,您可以使用nvarchar数据类型的变量或表列:

-- Variable
declare @var nvarchar(128) = N'DDFF5D36-F14D-495D-BAA6-3688786D6CFA123456789';

select HASHBYTES('SHA_256', @var);

-- Table column
declare @t table(
  Value nvarchar(128)
);

insert into @t
select @var;

select HASHBYTES('SHA_256', t.Value)
from @t t;

P.S。当然,由于Wintel是一个小端平台,SQL Server使用与OS /硬件相同版本的编码。除非SQL Server 2017中出现新的东西,否则无法在本机中本地获得big-endian表示。