Base64-Codierung in SQL Server 2005 T-SQL

124

Ich möchte eine T-SQL-Abfrage schreiben, in der ich eine Zeichenfolge als Base64-Zeichenfolge codiere. Überraschenderweise kann ich keine nativen T-SQL-Funktionen für die Base64-Codierung finden. Existiert eine native Funktion? Wenn nicht, wie lässt sich Base64 am besten in T-SQL codieren?

Jacob
quelle
1
Ich würde fragen, warum Daten als base64-Zeichenfolge gespeichert werden sollten. Es gibt einen guten Grund, base64 über http zu verwenden, nämlich die Interoperabilität zwischen Systemen sicherzustellen, die nur den ASCII-Zeichensatz unterstützen (und alle Daten als Text behandeln). Sie können ein Byte-Array einfach in Base-64 konvertieren und umgekehrt. Warum also nicht die Daten effizient speichern? Ich habe sogar gesehen, wie Leute base64-Strings in nvarchar-Spalten speichern, was 275% des Speicherplatzes von varbinary beansprucht, was zur Verschwendung von Festplatte, RAM, Netzwerk usw. führt.
The Dag
9
Hier geht es darum, eine base64-Zeichenfolge zu generieren, nicht eine zu speichern.
Jacob

Antworten:

187

Ich weiß, dass dies bereits beantwortet wurde, aber ich habe nur mehr Zeit damit verbracht, zuzugeben, dass ich einzeilige SQL-Anweisungen entwickelt habe, um dies zu erreichen. Deshalb werde ich sie hier teilen, falls jemand anderes dasselbe tun muss:

-- 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
;

Ich musste in der ersten (Codierungs-) Abfrage eine von Unterabfragen generierte Tabelle verwenden, da ich keine Möglichkeit fand, den ursprünglichen Wert ("TestData") in seine hexadezimale Zeichenfolgendarstellung ("5465737444617461") zu konvertieren, um ihn als Argument aufzunehmen xs: hexBinary () in der XQuery-Anweisung.

Ich hoffe das hilft jemandem!

Quecksilber
quelle
7
Beim Codieren funktioniert xs:base64Binary(sql:column("bin"))(ohne xs:hexBinaryAufruf) ebenfalls. Tolle Hilfe!
Amphetamachine
3
Um die Codierung von Unicode-Text zu unterstützen, sollten Sie 'N' vor TestData einfügen : 'SELECT CAST ( N ' TestData 'AS VARBINARY (MAX)) AS bin'
Kjetil Klaussen
Funktionierte nicht für Unicode-Text ... SELECT CAST (N '' AS XML) .value ('xs: base64Binary (xs: hexBinary (sql: column ("bin")))', 'VARCHAR (MAX)') Base64Encoding FROM (SELECT CAST (N 'मन्त्रीले उल्ट्याए सात छन् AS' AS VARBINARY (MAX)) AS bin) AS bin_sql_server_temp;
Hsuk
3
@hsuk varchar ist nicht mit Unicode kompatibel. Es funktioniert gut, wenn Sie stattdessen nvarchar (max) verwenden, zB:SELECT CAST( CAST(N'' AS XML).value( 'xs:base64Binary("LgkoCU0JJAlNCTAJQAkyCUcJIAAJCTIJTQkfCU0JLwk+CQ8JIAA4CT4JJAkgABsJKAlNCWQJ")' , 'VARBINARY(MAX)' ) AS NVARCHAR(MAX) ) UnicodeEncoding ;
AlwaysLearning
7
Weil Menschen manchmal bestimmte Dinge in Software aus Gründen erledigen müssen, die Sie nicht immer vorhersagen können ...?
Mercurial
87

Der einfachste und kürzeste Weg, den ich für SQL Server 2012 und höher finden konnte, ist BINARY BASE64:

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

Für Base64 zu string

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

(oder nvarchar(max)für Unicode-Zeichenfolgen)

Slai
quelle
1
Dies ist viel einfacher als die anderen Antworten und funktioniert genauso gut
sXe
2
Was ist der Zweck von BINARY BASE64 in der ersten Zeile? Wird es gebraucht? Ich habe es ohne versucht und es scheint das gleiche Ergebnis zu geben.
Mattpm
1
Der erste Ausschnitt ergab ein anderes Ergebnis als ich erwartet hatte; Ich habe "varbinary" in "varbinary (max)" geändert und die fehlenden Zeichen sind zusammengekommen
Hraefn
3
Dies sollte die Antwort sein, da die eigentliche Antwort Zeichenfolgenliterale erfordert und keine Variablen wie diese Antwort akzeptieren kann.
Matthew
2
Für base64 zu string stelle ich einen signifikanten Leistungsgewinn mit .value ('data [1]', 'varbinary (max)') vice .value ('.', 'Varbinary (max)') fest.
Geary M. McIver
25

Hier ist eine Modifikation der Antwort von mercurial, die auch die Unterabfrage für die Dekodierung verwendet und die Verwendung von Variablen in beiden Fällen ermöglicht.

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
Joey Gennari
quelle
22

Hier ist der Code für die Funktionen, die die Arbeit erledigen

-- 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

Anwendungsbeispiel:

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

Geben Sie hier die Bildbeschreibung ein

Oleg
quelle
Im Allgemeinen nützlich. Dies behandelte keine Zeichen wie Persisch und Russisch oder Emoji. zB سلام جیران oder В ооссии Base64 кодирует вас oder ❤️💥🤪🦌🎅⛄🎄🤐🙈🙉🙊💩
Hunter-Orionnoir
Du hast recht. Es behandelt nach dem Ersetzen von varchar zu nvarchar
Oleg
8

Ich habe die Antwort von @ Slai geliebt. Ich musste nur geringfügige Änderungen an den Einzeilern vornehmen, die ich suchte. Ich dachte, ich würde teilen, was ich am Ende hatte, falls es jemand anderem hilft, wie ich auf diese Seite zu stolpern:

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]
Jason W.
quelle
Für mich, ich brauchte die zweite Zeile zu ändern , VARBINARYzu VARBINARY(56), und dann hat es funktioniert.
Lee Grissom
Kürzeste Lösung, SQL Server 2005+ kompatibel.
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]

Dies ist nützlich zum Codieren und Decodieren.

Von Bharat J.

Bharat J.
quelle
0

Ich habe ein Skript erstellt, um einen vorhandenen in base64 codierten Hash in eine Dezimalzahl zu konvertieren. Dies kann nützlich sein:

SELECT LOWER(SUBSTRING(CONVERT(NVARCHAR(42), CAST( [COLUMN_NAME] as XML ).value('.','varbinary(max)'), 1), 3, 40)) from TABLE
Phate01
quelle
-1

Sie können nur verwenden:

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

Nach dem Codieren erhalten Sie den Text 'MjE4Nqk5'.

jasmintmp
quelle