Я не совсем уверен в вашей проблеме, но думаю, что вы копали не в том месте.
SQL -Сервер знает два типа строк для работы:
- 1-байтовая кодировка: расширенная ASCII, где параметры сортировки определяют все непростые латинские символы
- 2-байтовая кодировка: UCS-2, что почти совпадает с UTF-16
- Просто упомянуть: Начиная с v2019, существует специальные параметры сортировки, поддерживающие UTF8
Пока вы не смешиваете 1- и 2-байтовые строки в бинарных подходах это работает довольно хорошо.
Попробуйте это:
SELECT 'A½B' AS UsingASCII
,CAST('A½B' AS VARBINARY(MAX)) AS UsingASCIIasBinary
,N'A½B' AS UsingUCS2
,CAST(N'A½B' AS VARBINARY(MAX)) AS UsingUCS2asBinary
FOR XML PATH('')
возвращает
Text binary base64
A½B 0x41BD42 Qb1C
A½B 0x4100BD004200 QQC9AEIA
Вы можете увидеть HEX-коды 41, BD и 42 для три символа и 00, чтобы сделать его 2-байтовым UCS2 .
Кодовые точки 41 и 42 - это "A" и "B", в то время как кодовая точка BD обозначает ваш специальный символ.
SQL -Процесс сервера не является чудом ...
В SQL -Сервер оператор FOR XML
вернет нативный XML, формат вывода по умолчанию NVARCHAR(MAX)
. Конечно, это не будет UTF8.
Переконвертировать base64 из примера выше
DECLARE @xml XML=
N'<binaryASCII>Qb1C</binaryASCII>
<binaryUCS2>QQC9AEIA</binaryUCS2>';
SELECT @xml.value('(/binaryASCII)[1]','varbinary(max)')
,CAST(@xml.value('(/binaryASCII)[1]','varbinary(max)') AS VARCHAR(MAX)) ReconvertedFromASCII
,@xml.value('(/binaryUCS2)[1]','varbinary(max)')
,CAST(@xml.value('(/binaryUCS2)[1]','varbinary(max)') AS NVARCHAR(MAX)) ReconvertedFromUCS2;
Для чтения base64 в T- SQL требуется небольшой XML -хак:
Ваш пример base64:
SELECT CAST(CAST('VGFrZSC9IG9mIHRoZSB0b3RhbA==' AS XML)
.value('.','varbinary(max)') AS VARCHAR(MAX));
Моя система правильно возвращает символ "half". Это позволяет мне предположить, что ваше стандартное сопоставление сопоставляет другой / без символа с этой кодовой точкой.
Попробуйте выяснить ваше сопоставление по умолчанию и проверить параметры сопоставления соответствующих столбцов и прочитать о COLLATE
.