Кодировка Base64 в SQL Server 2005 T-SQL

124

Я хотел бы написать запрос T-SQL, в котором я кодирую строку как строку Base64. Удивительно, но я не могу найти никаких собственных функций T-SQL для кодирования Base64. Существует ли собственная функция? Если нет, то как лучше всего использовать кодировку Base64 в T-SQL?

Иаков
источник
1
Я бы спросил, почему данные должны храниться в виде строки base64. Есть веская причина использовать base64 вместо http, а именно то, что он обеспечивает взаимодействие между системами, которые не поддерживают ничего, кроме набора символов ASCII (и обрабатывают все данные как текст). Вы можете легко преобразовать байтовый массив в формат base-64 и наоборот, так почему бы не сохранить данные эффективно? Я даже видел, как люди хранят строки base64 в столбцах nvarchar, которые занимают 275% пространства varbinary, что приводит к потере дискового пространства, оперативной памяти, сети и т. Д.
The Dag
9
Речь идет о создании строки base64, а не о ее хранении.
Джейкоб

Ответы:

187

Я знаю, что на это уже был дан ответ, но я просто потратил больше времени, чем хотел бы признать, придумывая для этого однострочные операторы SQL, поэтому я поделюсь ими здесь на случай, если кому-то еще понадобится сделать то же самое:

-- Encode the string "TestData" in Base64 to get "VGVzdERhdGE="
SELECT
    CAST(N'' AS XML).value(
          'xs:base64Binary(xs:hexBinary(sql:column("bin")))'
        , 'VARCHAR(MAX)'
    )   Base64Encoding
FROM (
    SELECT CAST('TestData' AS VARBINARY(MAX)) AS bin
) AS bin_sql_server_temp;

-- Decode the Base64-encoded string "VGVzdERhdGE=" to get back "TestData"
SELECT 
    CAST(
        CAST(N'' AS XML).value(
            'xs:base64Binary("VGVzdERhdGE=")'
          , 'VARBINARY(MAX)'
        ) 
        AS VARCHAR(MAX)
    )   ASCIIEncoding
;

Мне пришлось использовать сгенерированную подзапросом таблицу в первом (кодированном) запросе, потому что я не мог найти способ преобразовать исходное значение («TestData») в его шестнадцатеричное строковое представление («5465737444617461»), чтобы включить его в качестве аргумента в xs: hexBinary () в операторе XQuery.

Я надеюсь, что это поможет кому-то!

ртутный
источник
7
При кодировании xs:base64Binary(sql:column("bin"))(без xs:hexBinaryвызова) тоже работает. Большая помощь!
amphetamachine
3
Для поддержки кодирования текста в Юникоде вы должны добавить «N» перед TestData : «SELECT CAST ( N 'TestData' AS VARBINARY (MAX)) AS bin»
Кьетил Клауссен
Не работает для текста в Юникоде ... SELECT CAST (N '' AS XML) .value ('xs: base64Binary (xs: hexBinary (sql: column ("bin")))', 'VARCHAR (MAX)') Base64Encoding FROM (SELECT CAST (N 'मन्त्रीले उल्ट्याए सात छन्।' AS VARBINARY (MAX)) AS bin) AS bin_sql_server_temp;
hsuk
3
@hsuk varchar несовместим с Unicode. Он отлично работает, если вы вместо этого используете nvarchar (max), например:SELECT CAST( CAST(N'' AS XML).value( 'xs:base64Binary("LgkoCU0JJAlNCTAJQAkyCUcJIAAJCTIJTQkfCU0JLwk+CQ8JIAA4CT4JJAkgABsJKAlNCWQJ")' , 'VARBINARY(MAX)' ) AS NVARCHAR(MAX) ) UnicodeEncoding ;
AlwaysLearning
7
Потому что иногда людям нужно выполнять определенные задачи в программном обеспечении по причинам, которые вы не всегда можете предсказать ...?
Mercurial
87

Самый простой и короткий способ для SQL Server 2012 и более поздних версий BINARY BASE64:

SELECT CAST('string' as varbinary(max)) FOR XML PATH(''), BINARY BASE64

Для Base64 для строки

SELECT CAST( CAST( 'c3RyaW5n' as XML ).value('.','varbinary(max)') AS varchar(max) )

(или nvarchar(max)для строк Unicode)

Slai
источник
1
Это намного проще, чем другие ответы, и работает так же хорошо
sXe
3
какова цель BINARY BASE64 в первой строке? Это нужно? Я пробовал без, и, похоже, результат тот же.
матпм,
1
Первый фрагмент дал мне другой результат, чем я ожидал; Я изменил "varbinary" на "varbinary (max)", и отсутствующие символы стали на свои места
Hraefn
3
Это должен быть ответ, потому что фактический ответ требует строковых литералов и не может принимать такие переменные, как этот ответ.
Мэтью,
2
Для преобразования base64 в строку я замечаю значительный прирост производительности с .value ('data [1]', 'varbinary (max)') vice .value ('.', 'Varbinary (max)').
Geary M. McIver
25

Вот модификация ответа mercurial, которая также использует подзапрос при декодировании, что позволяет использовать переменные в обоих случаях.

DECLARE
    @EncodeIn VARCHAR(100) = 'Test String In',
    @EncodeOut VARCHAR(500),
    @DecodeOut VARCHAR(200)    

SELECT @EncodeOut = 
    CAST(N'' AS XML).value(
          'xs:base64Binary(xs:hexBinary(sql:column("bin")))'
        , 'VARCHAR(MAX)'
    )
FROM (
    SELECT CAST(@EncodeIn AS VARBINARY(MAX)) AS bin
) AS bin_sql_server_temp;

PRINT @EncodeOut

SELECT @DecodeOut = 
CAST(
    CAST(N'' AS XML).value(
        'xs:base64Binary(sql:column("bin"))'
      , 'VARBINARY(MAX)'
    ) 
    AS VARCHAR(MAX)
) 
FROM (
    SELECT CAST(@EncodeOut AS VARCHAR(MAX)) AS bin
) AS bin_sql_server_temp;

PRINT @DecodeOut
Джои Дженнари
источник
22

Вот код функций, которые будут выполнять эту работу

-- To Base64 string
CREATE FUNCTION [dbo].[fn_str_TO_BASE64]
(
    @STRING NVARCHAR(MAX)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    RETURN (
        SELECT
            CAST(N'' AS XML).value(
                  'xs:base64Binary(xs:hexBinary(sql:column("bin")))'
                , 'NVARCHAR(MAX)'
            )   Base64Encoding
        FROM (
            SELECT CAST(@STRING AS VARBINARY(MAX)) AS bin
        ) AS bin_sql_server_temp
    )
END
GO

-- From Base64 string
CREATE FUNCTION [dbo].[fn_str_FROM_BASE64]
(
    @BASE64_STRING NVARCHAR(MAX)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    RETURN (
        SELECT 
            CAST(
                CAST(N'' AS XML).value('xs:base64Binary(sql:variable("@BASE64_STRING"))', 'VARBINARY(MAX)') 
            AS NVARCHAR(MAX)
            )   UTF8Encoding
    )
END

Пример использования:

DECLARE @CHAR NVARCHAR(256) = N'e.g., سلام جیران or В России'
SELECT [dbo].[fn_str_FROM_BASE64]([dbo].[fn_str_TO_BASE64](@CHAR)) as converted

введите описание изображения здесь

Олег
источник
В общем полезно. Здесь не обрабатывались символы вроде персидского и русского, а также эмодзи. например, سلام جیران или В России Base64 кодирует вас или ❤️💥🤪🦌🎅⛄🎄🤐🙈🙉🙊💩
Hunter-Orionnoir
Ты прав. Он обрабатывается после замены varchar на nvarchar
Олег
8

Мне понравился ответ @Slai. Мне нужно было внести очень незначительные изменения в однострочники, которые я искал. Я подумал, что поделюсь тем, что у меня получилось, на случай, если это поможет кому-то еще, наткнувшись на эту страницу, как я:

DECLARE @Source VARCHAR(50) = '12345'
DECLARE @Encoded VARCHAR(500) = CONVERT(VARCHAR(500), (SELECT CONVERT(VARBINARY, @Source) FOR XML PATH(''), BINARY BASE64))
DECLARE @Decoded VARCHAR(500) = CONVERT(VARCHAR(500), CONVERT(XML, @Encoded).value('.','varbinary(max)'))
SELECT @Source AS [Source], @Encoded AS [Encoded], @Decoded AS [Decoded]
Джейсон В
источник
Мне нужно было поменять вторую строку VARBINARYна VARBINARY(56), и тогда это сработало.
Ли Гриссом,
Кратчайшее решение, совместимое с SQL Server 2005+.
YB
1
DECLARE @source varbinary(max),  
@encoded_base64 varchar(max),  
@decoded varbinary(max) 
SET @source = CONVERT(varbinary(max), 'welcome') 
-- Convert from varbinary to base64 string 
SET @encoded_base64 = CAST(N'' AS xml).value('xs:base64Binary(sql:variable       
("@source"))', 'varchar(max)') 
  -- Convert back from base64 to varbinary 
   SET @decoded = CAST(N'' AS xml).value('xs:base64Binary(sql:variable             
  ("@encoded_base64"))', 'varbinary(max)') 

 SELECT
  CONVERT(varchar(max), @source) AS [Source varchar], 
   @source AS [Source varbinary], 
     @encoded_base64 AS [Encoded base64], 
     @decoded AS [Decoded varbinary], 
     CONVERT(varchar(max), @decoded) AS [Decoded varchar]

Это полезно для кодирования и декодирования.

Автор: Бхарат Дж.

Бхарат Дж
источник
0

Я сделал скрипт для преобразования существующего хэша, закодированного в base64, в десятичный, это может быть полезно:

SELECT LOWER(SUBSTRING(CONVERT(NVARCHAR(42), CAST( [COLUMN_NAME] as XML ).value('.','varbinary(max)'), 1), 3, 40)) from TABLE
Phate01
источник
-1

Вы можете использовать только:

Declare @pass2 binary(32)
Set @pass2 =0x4D006A00450034004E0071006B00350000000000000000000000000000000000
SELECT CONVERT(NVARCHAR(16), @pass2)

то после кодирования вы получите текст MjE4Nqk5

jasmintmp
источник