การเข้ารหัส Base64 ใน SQL Server 2005 T-SQL


124

ฉันต้องการเขียนแบบสอบถาม T-SQL โดยที่ฉันเข้ารหัสสตริงเป็นสตริง Base64 น่าแปลกที่ฉันไม่พบฟังก์ชัน T-SQL ดั้งเดิมสำหรับการเข้ารหัส Base64 มีฟังก์ชันดั้งเดิมหรือไม่? ถ้าไม่วิธีที่ดีที่สุดในการเข้ารหัส Base64 ใน T-SQL คืออะไร?


1
ฉันสงสัยว่าทำไมควรจัดเก็บข้อมูลเป็นสตริง base64 มีเหตุผลที่ดีที่จะใช้ base64 ผ่าน http นั่นคือเพื่อให้แน่ใจว่าสามารถทำงานร่วมกันได้ในระบบต่างๆที่สนับสนุนอะไรมากไปกว่าชุดอักขระ ASCII (และถือว่าข้อมูลทั้งหมดเป็นข้อความ) คุณสามารถแปลงอาร์เรย์ไบต์เป็นฐาน 64 และในทางกลับกันได้อย่างง่ายดายดังนั้นทำไมไม่จัดเก็บข้อมูลอย่างมีประสิทธิภาพ ฉันเคยเห็นผู้คนเก็บสตริง base64 ไว้ในคอลัมน์ nvarchar ซึ่งใช้พื้นที่ 275% ของ varbinary ซึ่งทำให้เสียดิสก์แรมเครือข่าย ฯลฯ
The Dag

9
นี่คือการสร้างสตริง base64 ไม่ใช่การจัดเก็บสตริง
Jacob

คำตอบ:


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
ในการรองรับการเข้ารหัสข้อความ Unicode คุณควรเพิ่ม '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 จาก (เลือก CAST (N 'मन्त्रीलेउल्ट्याएसातछन्।' เป็น VARBINARY (MAX)) AS bin) เป็น bin_sql_server_temp;
hsuk

3
@hsuk varchar ไม่สามารถใช้ร่วมกับ Unicode ได้ ใช้งานได้ดีถ้าคุณใช้ nvarchar (สูงสุด) แทนเช่นSELECT CAST( CAST(N'' AS XML).value( 'xs:base64Binary("LgkoCU0JJAlNCTAJQAkyCUcJIAAJCTIJTQkfCU0JLwk+CQ8JIAA4CT4JJAkgABsJKAlNCWQJ")' , 'VARBINARY(MAX)' ) AS NVARCHAR(MAX) ) UnicodeEncoding ;
AlwaysLearning

7
เพราะบางครั้งคนเราจำเป็นต้องทำบางสิ่งให้สำเร็จในซอฟต์แวร์ด้วยเหตุผลที่คุณไม่สามารถคาดเดาได้เสมอไป ... ?
mercurial

88

วิธีที่ง่ายและสั้นที่สุดที่ฉันสามารถหาได้สำหรับ 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

3
วัตถุประสงค์ของ BINARY BASE64 ในบรรทัดแรกคืออะไร? จำเป็นไหม? ฉันพยายามโดยไม่และดูเหมือนว่าจะให้ผลลัพธ์เดียวกัน
mattpm

1
ตัวอย่างแรกให้ผลลัพธ์ที่แตกต่างจากที่ฉันคาดไว้ ฉันเปลี่ยน "varbinary" เป็น "varbinary (สูงสุด)" และอักขระที่หายไปก็เข้าที่
Hraefn

3
นี่ควรเป็นคำตอบเนื่องจากคำตอบที่แท้จริงต้องใช้ตัวอักษรสตริงและไม่สามารถยอมรับตัวแปรเช่นคำตอบนี้ได้
Matthew

2
สำหรับ base64 เป็นสตริงฉันสังเกตเห็นการเพิ่มประสิทธิภาพที่สำคัญด้วย. value ('data [1]', 'varbinary (max)') secondary .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
Oleg

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)แล้วมันก็ใช้ได้
Lee Grissom

โซลูชันที่สั้นที่สุดเข้ากันได้กับ SQL Server 2005+
YB

4

ไม่ไม่มีฟังก์ชันดั้งเดิมวิธีนี้ใช้ได้ผลสำหรับฉันในอดีต: http://www.motobit.com/help/scptutl/sa306.htm
ดังนั้นจึงมีวิธีนี้:
http://www.vbforums.com/ showthread.php? t = 554886


3
บทความในลิงก์ที่สองมีประโยชน์มาก ขอบคุณ!
Jacob

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]

นี่เป็นประโยชน์สำหรับการเข้ารหัสและถอดรหัส

โดย Bharat J


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'

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.