18 февраля 2021

MS SQL Server. Преобразование из ASCII в HEX и обратно

    Попросили меня написать скрипт, который конвертировал данные из одной таблицы в другую. При этом одно из текстовых полей нужно "привести к верхнему регистру, взять символы в обратном порядке и преобразовать их из ASCII в HEX". Например, строка "XYZ" должна превратиться в "5A5958". Привести к верхнему регистру и взять символы в обратном порядке – это делают встроенные строковые функции UPPER и REVERSE. Но, преобразование из ASCII в HEX поставило меня в тупик. Гугл мне в помощь!
    Поиск дал множество самописных функций для преобразования символов из ASCII в HEX. И когда я уже хотел выбрать одну из них, на одном из форумов я натолкнулся на запрос:
select CAST('ZYX' as varbinary)
Он возвращает 0x5A5958. Простая, но хорошая идея. Остается двоичные данные преобразовать в строку и избавиться от "0x". Использование в запросе CAST натолкнуло меня на мысль проверить, как работает с varbinary функция CONVER, которая имеет дополнительный параметр конвертации – "style":
CONVERT ( data_type [ ( length ) ] , expression [ , style ] )
Если конвертация производится между типами данных binary/varbinary и char/varchar, то параметр style может принимать значение от 0 до 2.
    По умолчанию параметр style равен 0. В этом режиме функция CONVER преобразует символы ASCII в двоичные данные либо двоичные данные в символы ASCII. Запрос
select CONVERT(varbinary(max), 'ZYX')
аналогично CAST, преобразует строку в двоичные данные и вернет 0x5A5958. Соответственно запрос
select CONVERT(varchar(max), 0x5A5958)
произведет обратное преобразование двоичных данных в строку "ZYX".
    Если параметр style равен 1 или 2, то функция CONVER преобразует binary/varbinary в char/varchar и наоборот. Значение параметра style указывает на наличие символов 0x слева: 1 – символы есть, 2 – символов нет.
Преобразование строки в двоичные данные:
convert varchar to varbinary
Преобразование двоичных данных в строку:
convert varbinary to varchar
Обратите внимание на строку 2 в результатах – это то, что надо мне по заданию. Значит для того, чтобы представить ASCII-символы в шестнадцатеричном виде необходимо преобразовать строку в двоичные данные с параметром style равным 0, а полученный результат преобразовать в строку с параметром style равным 2:
CONVERT(varchar(max), CONVERT(varbinary(max), 'ZYX'), 2)
Для обратного преобразования строки, записанной в шестнадцатеричном виде в ASCII, необходимо преобразовать строку в двоичные данные с параметром style равным 2, а полученный результат преобразовать в строку с параметром style равным 0:
CONVERT(varchar(max), CONVERT(varbinary(max), '5A5958', 2))
    Для полноты освещения вопроса стоит упомянуть еще о недокументированной функции MS SQL Server для преобразования двоичных данных в строку:
create function sys.fn_varbintohexsubstring
(
   @fsetprefix bit = 1    -- append '0x' to the output
  ,@pbinin varbinary(max) -- input binary stream
  ,@startoffset int = 1   -- starting offset 
  ,@cbytesin int = 0      -- length of input to consider, 0 means total length
)
returns nvarchar(max)
Что бы записать строку шестнадцатеричными символами без символов 0x, как в примере с использованием функции CONVERT, вызовем fn_varbintohexsubstring с параметром @fsetprefix равным 0 и преобразуем результат к верхнему регистру:
UPPER(sys.fn_varbintohexsubstring(0, CONVERT(varbinary(max), 'ZYX'), 1, 0))

Комментариев нет:

Отправить комментарий