Как сделать побитовое исключающее ИЛИ в сервере SQL между двумя двоичными типами? - PullRequest
8 голосов
/ 29 января 2011

По этой ссылке: Битовые операторы (Transact-SQL) мы можем делать побитовые операции между двоичными и int, smallint, tinyint или наоборот.

Но как я могу сделать побитовыеисключительное ИЛИ в sql server между двумя двоичными типами?Или, если это невозможно, как я могу разделить двоичный файл / varbinary на отдельные байты?

Причина, по которой я это спрашиваю, заключается в том, что мне нужно xor на два числа больше, чем значение max int.Спасибо.

Ответы [ 4 ]

6 голосов
/ 29 января 2011

Все комментарии в блоке кода

-- 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)))
2 голосов
/ 29 января 2011

Комментарий в вопросе от Мартина дал мне идею, как разделить двоичный файл, чтобы я мог XOR значения.Первоначально я хотел XOR два GUID в SQL.Итак, вот код, с которым я пришел:

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

Функция для преобразования двоичной в шестнадцатеричную строку имеет вид: Преобразование двоичных данных в шестнадцатеричную строку

Я знаю, чтов SQL 2008 мы можем использовать функцию конвертирования, чтобы сделать это, как объяснялось в этом посте: SQL Server 2008: новое двоичное преобразование - шестнадцатеричная строка , но в моем случае это не было вариантом.

Однакобыло бы хорошо, если бы кто-то лучше представлял, как мы можем использовать побитовые операции SQL для двоичного типа данных.

РЕДАКТИРОВАТЬ:

Спасибо cyberkiwi за предоставление правильного алгоритма и за указание на ошибку вмой кодЭтот код может быть полезен для двоичного кода XOR, но не для идентификаторов GUID, поскольку идентификаторы GUID имеют разный порядок байтов для первых и последних 8 байтов.Пожалуйста, посмотрите объяснение в Википедии об этом: Базовая структура GUID .Обратите внимание, что если вы собираетесь использовать результат XOR в качестве реального GUID, вы должны принять во внимание биты версии.

2 голосов
/ 29 января 2011

По документации Битовая исключительная ИЛИ :

Примечание

Только одно выражение может иметь двоичный или переменный тип данных. в побитовой операции.

1 голос
/ 29 января 2011

Я использовал bigints для хранения обоих значений. Таким образом, вы получите больший диапазон. Если значение больше, чем bigint, вам может потребоваться разделить значения на два bigint и использовать комбинацию оператора AND / OR.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...