SQL Server конвертирует varbinary(16) в двоичный текст

Аналогично этому вопросу (сервер Sql преобразует целое число в двоичную строку, но Вместо этого я хотел бы преобразовать varbinary(16) в его текстовую версию.

Я делаю что-то трагически неправильное, о чем свидетельствуют результаты моего кода.

create function GetGuidBinaryString (@value varbinary(16))
returns varchar(128)
as
begin
declare @vsresult varchar(128) 
declare @inti int 
select @inti = 128, @vsresult = '' 
while @inti>0 
begin 
select @vsresult=convert(char(1), @value % 2)+@vsresult 
select @value = convert(int, (@value / 2)), @inti=@inti-1 
end 

return @vsresult
end


create table #values (binvalue varchar(128))

delete from #values

declare @intcount int
select @intcount = 0
while @intcount < 100
begin
    insert into #values select dbo.GetGuidBinaryString(convert(varbinary(16),convert(bigint,2147483640) + @intcount))
    select @intcount = @intcount+1
end


select * from #values

Возможно, я выполняю какое-то неявное преобразование в функции, поскольку функция правильно работает только для положительных целых чисел.


person Nat    schedule 14.01.2011    source источник


Ответы (1)


@value % 2 и @value / 2 выполняют неявное преобразование.

select @value = convert(int, (@value / 2)) выполняет явное преобразование в int, поэтому здесь вы получаете отрицательное целое для значений, хранящихся в varbinary(16), которые после деления, преобразованного в bigint, превышают 2 147 483 647. % для отрицательного int даст вам -1.

Я не думаю, что можно преобразовать varbinary(16) в двоичный файл, используя % и /. Они работают только с int/bigint и т.д.

Вот процедура преобразования, которая работает для положительных значений bigint. Я не знаю, какое представление вы ожидаете для отрицательных значений bigint. Преобразуйте свое поле varbinary(16) в bigint при вызове функции, и, возможно, оно сделает то, что вы хотите. Я уверен, что это не работает для всех возможных значений, которые вы можете хранить в поле varbinary(16).

create function BigIntToBin (@v bigint)
returns varchar(256)
as
begin
    declare @res varchar(256)
    declare @i int

    set @i = 128
    set @res = ''

    while @i > 0
    begin
        if @v % 2 = 0
            set @res = '0' + @res
        else    
            set @res = '1' + @res
        set @v = @v / 2
        set @i = @i - 1
    end
    return @res
end
person Mikael Eriksson    schedule 14.01.2011
comment
Ваше здоровье. Чтобы получить полный диапазон, я должен создать функцию CLR. - person Nat; 16.01.2011