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?


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!


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)


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

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


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]

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


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

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.