修复插入时不带 N 前缀的损坏的 utf8 nvarchar 值

Hey*_*ude 4 sql-server collation utf-8 unicode

是否可以从没有前缀的损坏的 nvarchar 中恢复 UTF8 数据N

\n

例如,在下面的代码片段中,我希望@n1_fixed基于以下内容获得正确的值@n1

\n
declare\n  @n1 nvarchar(10) = '\xe1\xb8\xbe\xe1\xba\xa5xi\xe1\xb8\xbf\xe1\xbb\xa9\xc5\x9b',\n  @n2 nvarchar(10) = N'\xe1\xb8\xbe\xe1\xba\xa5xi\xe1\xb8\xbf\xe1\xbb\xa9\xc5\x9b';\n\ndeclare\n  @n1_fixed nvarchar(10); -- somehow make it have the correct value, based on @n1\n\nselect iif(@n1_fixed = @n2, 1, 0)\n
Run Code Online (Sandbox Code Playgroud)\n

Dan*_*man 12

无法恢复原始值。

\n

N不带前缀表示国家字符的字符常量将根据数据库默认排序规则代码页进行转换。如果源字符不存在明确的映射,则该值将更改为后备字符。?当不存在替代字符时,此后备可能是相似但不同的字符或值。

\n

您可以通过将该值转换为 varbinary 来观察这一点。使用默认数据库排序规则的示例SQL_Latin1_General_CP1_CI_AS,使用代码页 1252:

\n
DECLARE @n1 nvarchar(10) = \'\xe1\xb8\xbe\xe1\xba\xa5xi\xe1\xb8\xbf\xe1\xbb\xa9\xc5\x9b\', @n2 nvarchar(10) = N\'\xe1\xb8\xbe\xe1\xba\xa5xi\xe1\xb8\xbf\xe1\xbb\xa9\xc5\x9b\';\nSELECT \n      @n1 AS corrupted_string\n    , CAST(@n1 AS varbinary(100)) AS corrupted_raw_value\n    , @n2 AS correct_string\n    , CAST(@n2 AS varbinary(100)) AS correct_raw_value;\nGO\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
损坏的字符串损坏的原始值正确的字符串正确的原始值
??xi??s0x3F003F00780069003F003F007300\xe1\xb8\xbe\xe1\xba\xa5xi\xe1\xb8\xbf\xe1\xbb\xa9\xc5\x9b0x3E1EA51E780069003F1EE91E5B01
\n
\n

具有数据库默认排序规则的同一脚本的结果Albanian_100_CI_AS显示,由于 1250 代码页,最后一个字符已正确映射,但更改为 \'?\' 后备的字符将像前面的示例一样永久丢失。

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
损坏的字符串损坏的原始值正确的字符串正确的原始值
??xi??\xc5\x9b0x3F003F00780069003F003F005B01\xe1\xb8\xbe\xe1\xba\xa5xi\xe1\xb8\xbf\xe1\xbb\xa9\xc5\x9b0x3E1EA51E780069003F1EE91E5B01
\n