Pengkodean Base64 di SQL Server 2005 T-SQL

124

Saya ingin menulis kueri T-SQL di mana saya menyandikan string sebagai string Base64. Anehnya, saya tidak dapat menemukan fungsi T-SQL asli untuk melakukan pengkodean Base64. Apakah fungsi asli ada? Jika tidak, apa cara terbaik untuk melakukan pengkodean Base64 di T-SQL?

Yakub
sumber
1
Saya akan mempertanyakan mengapa data harus disimpan sebagai string base64. Ada alasan bagus untuk menggunakan base64 melalui http, yaitu memastikan interoperabilitas di seluruh sistem yang mendukung tidak lebih dari kumpulan karakter ASCII (dan yang memperlakukan semua data sebagai teks). Anda dapat dengan mudah mengonversi array byte ke basis 64 dan sebaliknya, jadi mengapa tidak menyimpan data secara efisien? Saya bahkan pernah melihat orang menyimpan string base64 di kolom nvarchar, yang mengambil 275% ruang varbinary, yang menyebabkan pemborosan disk, ram, jaringan, dll.
The Dag
9
Ini tentang membuat string base64, bukan menyimpannya.
Yakub

Jawaban:

187

Saya tahu ini telah dijawab, tetapi saya hanya menghabiskan lebih banyak waktu daripada yang saya akui datang dengan pernyataan SQL baris tunggal untuk mencapai ini, jadi saya akan membagikannya di sini jika ada orang lain yang perlu melakukan hal yang sama:

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

Saya harus menggunakan tabel yang dihasilkan subkueri di kueri (pengkodean) pertama karena saya tidak dapat menemukan cara untuk mengonversi nilai asli ("TestData") menjadi representasi string hex ("5465737444617461") untuk disertakan sebagai argumen untuk xs: hexBinary () dalam pernyataan XQuery.

Saya harap ini membantu seseorang!

lincah
sumber
7
Saat encoding, xs:base64Binary(sql:column("bin"))(tanpa xs:hexBinarypanggilan) juga berfungsi. Sangat membantu!
amphetamachine
3
Untuk mendukung pengkodean teks unicode, Anda harus menambahkan 'N' di depan TestData : 'SELECT CAST ( N ' TestData 'AS VARBINARY (MAX)) AS bin'
Kjetil Klaussen
Tidak berfungsi untuk teks unicode ... SELECT CAST (N '' AS XML) .value ('xs: base64Binary (xs: hexBinary (sql: column ("bin")))', 'VARCHAR (MAX)') Base64Encoding DARI (PILIH CAST (N 'मन्त्रीले उल्ट्याए सात छन्।' AS VARBINER (MAX)) AS bin) AS bin_sql_server_temp;
hsuk
3
@hsuk varchar tidak kompatibel dengan Unicode. Ini berfungsi dengan baik jika Anda menggunakan nvarchar (max) sebagai gantinya, misalnya:SELECT CAST( CAST(N'' AS XML).value( 'xs:base64Binary("LgkoCU0JJAlNCTAJQAkyCUcJIAAJCTIJTQkfCU0JLwk+CQ8JIAA4CT4JJAkgABsJKAlNCWQJ")' , 'VARBINARY(MAX)' ) AS NVARCHAR(MAX) ) UnicodeEncoding ;
AlwaysLearning
7
Karena terkadang orang perlu menyelesaikan hal-hal tertentu dalam perangkat lunak karena alasan yang tidak selalu dapat Anda prediksi ...?
lincah
87

Cara termudah dan terpendek yang dapat saya temukan untuk SQL Server 2012 dan yang lebih baru adalah BINARY BASE64:

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

Untuk Base64 menjadi string

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

(atau nvarchar(max)untuk string Unicode)

Slai
sumber
1
Ini jauh lebih sederhana daripada jawaban lain, dan bekerja dengan baik
sXe
3
apa tujuan BINARY BASE64 di baris pertama? Apakah itu dibutuhkan? Saya mencoba tanpa dan tampaknya memberikan hasil yang sama.
mattpm
1
Cuplikan pertama memberi saya hasil yang berbeda dari yang saya harapkan; Saya mengubah "varbinary" menjadi "varbinary (max)" dan karakter yang hilang masuk ke tempatnya
Hraefn
3
Ini harus menjadi jawaban karena jawaban sebenarnya membutuhkan literal string dan tidak dapat menerima variabel seperti jawaban ini bisa.
Matius
2
Untuk base64 ke string, saya memperhatikan peningkatan kinerja yang signifikan dengan .value ('data [1]', 'varbinary (max)') vice .value ('.', 'Varbinary (max)').
Geary M. McIver
25

Berikut adalah modifikasi jawaban mercurial yang menggunakan subquery pada decode juga, memungkinkan penggunaan variabel di kedua contoh.

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

Berikut adalah kode untuk fungsi yang akan bekerja

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

Contoh penggunaan:

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

masukkan deskripsi gambar di sini

Oleg
sumber
Bermanfaat secara umum. Ini tidak menangani karakter apa pun seperti persia dan Rusia, atau emoji. misalnya, سلام جیران atau В России Base64 кодирует вас atau ❤️💥🤪🦌🎅⛄🎄🤐🙈🙉🙊💩
Hunter-Orionnoir
Kamu benar. Ini menangani setelah mengganti varchar ke nvarchar
Oleg
8

Saya menyukai jawaban @ Slai. Saya hanya perlu membuat sedikit modifikasi pada satu baris yang saya cari. Saya pikir saya akan membagikan apa yang saya dapatkan jika itu membantu orang lain tersandung ke halaman ini seperti yang saya lakukan:

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.
sumber
Bagi saya, saya perlu mengubah baris kedua VARBINARYmenjadi VARBINARY(56), dan kemudian berhasil.
Lee Grissom
Solusi terpendek, kompatibel dengan 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]

Ini berguna untuk encode dan decode.

Oleh Bharat J

Bharat J
sumber
0

Saya membuat skrip untuk mengubah hash yang ada yang dikodekan dalam base64 menjadi desimal, semoga bermanfaat:

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

Anda dapat menggunakan hanya:

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

kemudian setelah encoding Anda akan menerima teks 'MjE4Nqk5'

jasmintmp.dll
sumber