Lal*_*sin 6 sql-server postgresql unicode utf-8 utf-16
为了编写一些代码来对SQL Server和PostgreSQL中存储的数据进行一致性检查,我计划为这两个数据库计算表数据的MD5,并验证它们是否相等.只要数据是纯文本(ANSI),这样就可以正常工作,如下所示:
sql-server> SELECT master.dbo.fn_varbintohexstr(HashBytes('MD5', 'a'));
0x0cc175b9c0f1b6a831c399e269772661
postgres=# select MD5('a');
0cc175b9c0f1b6a831c399e269772661
Run Code Online (Sandbox Code Playgroud)
现在,如果我尝试使用一些韩文(韩文)字符,MD5匹配失败:
sql-server> SELECT master.dbo.fn_varbintohexstr(HashBytes('MD5', '?'));
0x7827b52f65d9f7777d37071cbbbf7f2d
postgres=# select MD5('?');
cb3e9be1a3a28b355eabae1fa1e291b3
Run Code Online (Sandbox Code Playgroud)
根据我的理解,不匹配的原因是unicode字符存储为SQL Server中的UCS-2编码(固定16位编码)和PostgreSQL中的UTF-8编码.由于MD5适用于字符位,因此SQL Server和PostgreSQL中的字符位序列会有所不同.
由于我一直主要处理韩文字符集,我在PostgreSQL中使用的解决方法是在计算哈希之前将编码从UTF-8转换为UHC(通用韩文字符集),如下所示:
postgres=# select MD5(CONVERT('?'::bytea,'UTF8','UHC'));
7827b52f65d9f7777d37071cbbbf7f2d
Run Code Online (Sandbox Code Playgroud)
如您所见,上面的哈希值与SQL Server的哈希值相同.
只要我处理韩文字符,一切都很好.但是有些表包含韩文和汉字的混合,在这种情况下转换失败:
postgres=# select MD5(CONVERT('??'::bytea,'UTF8','UHC'));
ERROR: character 0xe4b988 of encoding "UTF8" has no equivalent in "UHC"
postgres=#
Run Code Online (Sandbox Code Playgroud)
错误是有道理的,因为UHC字符集中没有相应的中文字符.
我怎样才能使它工作?基本上,我需要找到在SQL Server中将UCS-2转换为UTF-8的方法,或者在计算MD5之前将UTF-8转换为PostgreSQL中的UCS-2.我想在数据库引擎中执行所有这些操作,而不是在外部应用程序中加载数据来计算MD5,因为有些表具有庞大的数据集.
SQL Server版本2005 PostgreSQL版本9.1
不幸的是,PostgreSQL 也不支持 UTF-16 / UCS-2。
\n\n但是,您可以编写一个函数,将 utf8 转换text为 ucs2 二进制数据 ( bytea):
create or replace function text_to_ucs2be(input_in_utf8 text)\n returns bytea\n immutable\n strict\n language sql\nas $$\n select decode(string_agg(case\n when code_point < 65536\n then lpad(to_hex(code_point), 4, '0')\n end, ''), 'hex')\n from regexp_split_to_table(input_in_utf8, '') chr,\n ascii(chr) code_point\n$$;\n\ncreate or replace function text_to_ucs2le(input_in_utf8 text)\n returns bytea\n immutable\n strict\n language sql\nas $$\n select decode(string_agg(case\n when code_point < 65536\n then lpad(to_hex(code_point & 255), 2, '0')\n || lpad(to_hex(code_point >> 8), 2, '0')\n end, ''), 'hex')\n from regexp_split_to_table(input_in_utf8, '') chr,\n ascii(chr) code_point\n$$;\nRun Code Online (Sandbox Code Playgroud)\n\n注意:上面的这些函数将删除任何非 BMP 代码点(因此其中的名称为 ucs2)。
\n\n以下语句应该给出相同的结果:
\n\n-- on PostgreSQL\nselect md5(text_to_ucs2le('\xeb\xac\xb4'));\n\n-- on SQL server\nselect master.dbo.fn_varbintohexstr(HashBytes('MD5', N'\xeb\xac\xb4'));\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
1428 次 |
| 最近记录: |