How to do bitwise exclusive OR in sql server between two binary types?

后端 未结 4 1496
心在旅途
心在旅途 2021-01-05 03:16

According this link: Bitwise Operators (Transact-SQL) we can do bitwise operation between binary and int, smallint, tinyint or vice versa.

But how can I make a bitwi

相关标签:
4条回答
  • 2021-01-05 03:50

    All comments in code block

    -- variables
    declare @vb1 binary(16), @vb2 binary(16), @lo binary(8), @hi binary(8)
    
    -- 2 guids to compare
    declare @guid1 uniqueidentifier set @guid1 = '96B4316D-1EA7-4CA3-8D50-FEE8047C1329'
    declare @guid2 uniqueidentifier set @guid2 = 'FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF'
    
    -- split every 8 bytes into a binary(8), which is a bigint, the largest size usable with XOR
    select @vb1 = @guid1, @vb2 = @guid2
    
    -- xor the high and low parts separately
    select @hi = convert(binary(8), substring(@vb1,1,8)) ^ convert(bigint, substring(@vb2,1,8))
    select @lo = convert(binary(8), substring(@vb1,9,8)) ^ convert(bigint, substring(@vb2,9,8))
    
    -- the final result, concatenating the bytes using char(8) - binary -> uniqueidentifier
    select 'A', @guid1 union all
    select 'B', @guid2 union all
    select 'A XOR B = ', convert(uniqueidentifier, convert(binary(16),convert(char(8),@hi) + convert(char(8),@lo)))
    
    0 讨论(0)
  • 2021-01-05 03:57

    I used bigints for storing both values. This way you'll get more range. If the value is bigger than bigint, you might need to split the values in two bigint and use AND / OR operator combination.

    0 讨论(0)
  • 2021-01-05 04:01

    Per the Bitwise Exclusive OR documentation:

    Note

    Only one expression can be of either binary or varbinary data type in a bitwise operation.

    0 讨论(0)
  • 2021-01-05 04:14

    The comment in the question from Martin, gave me an idea how to split binary so I can XOR the values. Originally I wanted to XOR two GUIDs in sql. So here is the code I came with:

    declare @guid1 uniqueidentifier
    declare @guid2 uniqueidentifier
    declare @guid3_hi binary(8)
    declare @guid3_lo binary(8)
    declare @guid3_temp varchar(32)
    declare @guid3_char varchar(36)
    declare @guid3 uniqueidentifier
    
    set @guid1 = '96B4316D-1EA7-4CA3-8D50-FEE8047C1329'
    set @guid2 = 'FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF'
    
    set @guid3_hi = CAST(SUBSTRING(CAST(@guid1 as binary(16)),1,8) as bigint) ^ CAST(SUBSTRING(CAST(@guid2 as binary(16)),1,8) as bigint)
    set @guid3_lo = CAST(SUBSTRING(CAST(@guid1 as binary(16)),9,8) as bigint) ^ CAST(SUBSTRING(CAST(@guid2 as binary(16)),9,8) as bigint)
    
    set @guid3_temp = SUBSTRING(dbo.sp_hexadecimal(@guid3_hi), 3, 16) + SUBSTRING(dbo.sp_hexadecimal(@guid3_lo), 3, 16)
    select @guid3_temp
    
    set @guid3_char = SUBSTRING(@guid3_temp, 1, 8) + '-' + SUBSTRING(@guid3_temp, 9, 4) + '-' + SUBSTRING(@guid3_temp, 13, 4) + '-' + SUBSTRING(@guid3_temp, 17, 4) + '-' + SUBSTRING(@guid3_temp, 21, 12)
    select @guid3_char
    
    set @guid3 = convert(uniqueidentifier, @guid3_char)
    select @guid3
    
    --result 92CE4B69-58E1-5CB3-72AF-0117FB83ECD6
    

    The function to convert binary to hex string is from: Converting Binary Data to Hexadecimal String

    I know that in SQL 2008 we can use convert function to do this as this post explained: SQL Server 2008 : new binary – hex string conversion, but this was not an option in my case.

    However it will be good if someone has a better idea how we can use SQL bitwise operations on binary data type.

    EDIT:

    Thanks to cyberkiwi for providing the correct algorithm and for point the error in my code. This code could be good for XOR-ing binary but not for GUIDs, as GUIDs have different byte order for first and last 8 bytes. Please look at the wikipedia explanation for this: GUID Basic structure. Note that if you are going to use the XOR-ed result as real GUID you should take and into account the version bits.

    0 讨论(0)
提交回复
热议问题