Gee*_*_SO 4 sql-server collation sql-server-2012 encoding unicode
我一直在研究如何使用 SQL Server 解码 Base64,在网上搜索了许多解决方案(一些来自此处)后,似乎基于这种方法。
SELECT CAST(CAST('Base64StringHere' as XML ).value('.','varbinary(max)') AS VARCHAR(250))
Run Code Online (Sandbox Code Playgroud)
当我有 ASCII 文本时,这非常有效。但是,当我有以下法语文本时,它会损坏(大概是由于 VARCHAR 的限制)。
Où est le café le plus proche?
T8O5IGVzdCBsZSBjYWbDqSBsZSBwbHVzIHByb2NoZT8=
Run Code Online (Sandbox Code Playgroud)
并提供以下输出。
Où est le café le plus proche?
Run Code Online (Sandbox Code Playgroud)
我认为相对简单的解决方法是将 to 更改为CAST,NVARCHAR但这会再次导致损坏。
SELECT CAST(CAST('T8O5IGVzdCBsZSBjYWbDqSBsZSBwbHVzIHByb2NoZT8=' as XML ).value('.','varbinary(max)') AS NVARCHAR(250) )
????????????????
Run Code Online (Sandbox Code Playgroud)
我的搜索引擎技能可能让我失望,但我似乎找不到其他有我问题的人。
有什么想法吗?
Sol*_*zky 10
问题是您将 UTF-8 编码的字符串编码为 Base64。因此,解码 Base64 会返回原始的 UTF-8 字节序列。SQL Server 仅将 UTF-16 Little Endian 用于NVARCHAR数据,甚至用于 XML。因此,ù是ù(0xC3和 0xB9)的两字节 UTF-8 序列的 8 位版本。
幸运的是,它是可以将UTF-8编码的字符串转换为UTF-16,或甚至非Unicode代码页(IF代码页支持被转换所有字符)。诀窍是将 Base64 解码的字节,以它们的文本表示(即使是转换不正确的字符)转换为 XML。这个技巧的技巧是你需要添加<?xml ...>声明(通常省略)并指定源编码:
DECLARE @Base64Value NVARCHAR(500) = N'T8O5IGVzdCBsZSBjYWbDqSBsZSBwbHVzIHByb2NoZT8=';
DECLARE @BinaryValue VARBINARY(500) =
CONVERT(XML, @Base64Value).value('.','varbinary(max)');
DECLARE @IntermediaryValue VARCHAR(500) = CONVERT(VARCHAR(500), @BinaryValue);
SELECT @BinaryValue, @IntermediaryValue;
-- 0x4FC3B920657374206C6520636166C3A9206C6520706C75732070726F6368653F
-- O?¹ est le caf?© le plus proche?
-- This is to NVARCHAR, which will always work:
SELECT CONVERT(NVARCHAR(500),
CONVERT(XML, '<?xml version="1.0" encoding="UTF-8"?>' + @IntermediaryValue)
);
-- Où est le café le plus proche?
-- This is to VARCHAR, but "success" will depend on the Code Page
-- specified by the default Collation of the current Database:
SELECT CONVERT(VARCHAR(500),
CONVERT(XML, '<?xml version="1.0" encoding="UTF-8"?>' + @IntermediaryValue)
);
-- In a DB with a Latin1_General Collation it works:
-- Où est le café le plus proche?
-- In a DB with a Hebrew Collation, it gets the following error:
/*
Msg 6355, Level 16, State 1, Line XXXXX
Conversion of one or more characters from XML to target collation impossible
*/
Run Code Online (Sandbox Code Playgroud)
请注意,此技巧仅适用于从各种源编码转换为UTF-16 Little Endian(因为这是 SQL Server 中的 XML 数据类型在内部存储字符串的方式)。此方法不能用于将 UTF-16 转换为 UTF-8 或其他一些非 SQL Server 支持的编码。
下面是一个封装了上述步骤的 Inline-TVF:
GO
CREATE FUNCTION dbo.ConvertBase64EncodedUTF8ToUTF16LE
(
@Base64EncodedUTF8String VARCHAR(8000)
)
RETURNS TABLE
AS RETURN
SELECT
CONVERT(NVARCHAR(500),
CONVERT(XML,
'<?xml version="1.0" encoding="UTF-8"?>' +
CONVERT(VARCHAR(500),
CONVERT(XML, @Base64EncodedUTF8String)
.value('.','varbinary(max)')
)
)
) AS [DecodedValue];
GO
Run Code Online (Sandbox Code Playgroud)
然后测试:
SELECT *
FROM dbo.ConvertBase64EncodedUTF8ToUTF16LE(
'T8O5IGVzdCBsZSBjYWbDqSBsZSBwbHVzIHByb2NoZT8=');
-- Où est le café le plus proche?
Run Code Online (Sandbox Code Playgroud)
CROSS APPLY如果执行基于集合的操作,只需使用 with 。
| 归档时间: |
|
| 查看次数: |
11272 次 |
| 最近记录: |