Кодування Base64 в T-SQL SQL Server 2005


124

Я хотів би написати запит T-SQL, де я кодую рядок як рядок Base64. Дивно, але я не можу знайти жодних власних функцій T-SQL для кодування Base64. Чи існує нативна функція? Якщо ні, то який найкращий спосіб зробити кодування Base64 у T-SQL?


1
Я б сумнівався, чому дані слід зберігати як рядок base64. Існує вагомий привід використовувати base64 через http, а саме те, що він забезпечує взаємодію між системами, які підтримують не більше ніж набір символів ASCII (і які трактують усі дані як текст). Ви можете легко перетворити байтовий масив в base-64 і навпаки, так чому б не зберігати дані ефективно? Я навіть бачив, як люди зберігають base64-рядки в стовпцях nvarchar, що займає 275% простору варбінарів, що призводить до втрати диска, оперативної пам’яті, мережі тощо
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виклику). Чудова допомога!
амфетамахін

3
Щоб підтримати кодування тексту унікоду, слід додати "N" перед TestData : "SELECT CAST ( N 'TestData" AS VARBINARY (MAX)) AS bin "
Kjetil Klaussen

Не працював текст Unicode ... 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
Тому що інколи людям потрібно виконувати певні речі в програмному забезпеченні з причин, які не завжди можна передбачити ...?
ртутний

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)


1
Це набагато простіше, ніж інші відповіді, і працює так само добре
sXe

2
яка мета BINARY BASE64 у першому рядку? Це потрібно? Я пробував без і, здається, дає такий же результат.
матчпм

1
Перший фрагмент дав мені інший результат, ніж я очікував; Я змінив "varbinary" на "varbinary (max)", і зниклі символи
прийшли

3
Це має бути відповіддю, оскільки для реальної відповіді потрібні літеральні рядки і не можуть приймати такі змінні, як ця відповідь.
Метью

2
Для base64 до string, я помічаю значне посилення perf з .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

Ти маєш рацію. Він обробляє після заміни
Олег

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

4

Ні, немає рідної функції, цей метод працював для мене в минулому: http://www.motobit.com/help/scptutl/sa306.htm,
таким чином, є цей метод:
http://www.vbforums.com/ showthread.php? t = 554886


3
Стаття у другому посиланні була дуже зручною. Дякую!
Яків

1
Так, друге посилання є досить корисним
відкривається

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

-1

Ви можете використовувати лише:

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

після кодування ви отримаєте текст "MjE4Nqk5"

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.