Перетворити ціле число на шістнадцяткове та шістнадцяткове на ціле


78

Отже, у мене цей запит працює (де signal_dataстовпець) у Sybase, але він не працює в Microsoft SQL Server:

HEXTOINT(SUBSTRING((INTTOHEX(signal_data)),5,2)) as Signal

У мене також є в Excel (де A1міститься значення):

=HEX2DEC(LEFT(DEC2HEX(A1),LEN(DEC2HEX(A1))-2))

Хтось знає, як би я це зробив у SQL Server?

Відповіді:


119

Перетворити INT на шістнадцятковий:

SELECT CONVERT(VARBINARY(8), 16777215)

Перетворити hex на INT:

SELECT CONVERT(INT, 0xFFFFFF)

Оновлення 2015-03-16

Наведений приклад має обмеження, що він працює лише тоді, коли значення HEX задано як цілочисельний літерал. Для повноти, якщо значення для перетворення є шістнадцятковим рядком (наприклад, знайденим у стовпці varchar), використовуйте:

-- If the '0x' marker is present:
SELECT CONVERT(INT, CONVERT(VARBINARY, '0x1FFFFF', 1))

-- If the '0x' marker is NOT present:
SELECT CONVERT(INT, CONVERT(VARBINARY, '1FFFFF', 2))

Примітка: Рядок повинен містити парну кількість шістнадцяткових цифр. Непарна кількість цифр дасть помилку.

Детальніше можна знайти в розділі "Бінарні стилі" в CAST і CONVERT (Transact-SQL) . Я вважаю, що потрібен SQL Server 2008 або пізнішої версії.


8
Перетворивши його на VARBINARY, ви отримаєте дані у шістнадцятковому значенні. Струнні операції на ньому виконувати не можна
Паван

1
@ Білл Карвін, Паван прав. Sql Server 2008 може зробити це за допомогою convertфункції, але 2005 і нижче не можуть.
Бен

2
При використанні 8-символьної шістнадцяткової лінії, наприклад з ARGB, перетворіть у BIGINT замість INT. Максимальне значення для INT становить лише 2 147 483 647, або 7FFFFFFF. Обережно, використовуючи INT, повернення назад до hex буде працювати, але результати відрізняються від Hex2Dec Excel.
DenverJT

SELECT CONVERT(INT, CONVERT(varbinary, '01', 2))повертається 12337 (SQL Server 2005)
Ян Бойд,

Перші приклади не перетворюються в шістнадцяткові: вони перетворюються в двійкові. (Двійкове значення існує незалежно від будь-якої числової бази: Числова база має сенс лише в контексті рядкового подання.) (Крім того, параметр не повинен бути буквальним (хоча він повинен бути цілим числом.)) Вони можуть здаватися наче перетворюються в шістнадцяткову, оскільки при перетворенні двійкового файлу в рядок (наприклад, для його відображення) він за замовчуванням представляє його в шістнадцятковому. (Це може бути використано для перетворення в шістнадцяткову систему, як показано у відповіді @ KipBryan, але відповіді DenNukem та wndproc простіші.)
Джон Б. Ламб,

46

Власне, вбудована функція має ім'я master.dbo.fn_varbintohexstr.

Так, наприклад:

SELECT 100, master.dbo.fn_varbintohexstr(100)

Дає вам

100 0x00000064


3
Дивіться dba.stackexchange.com/questions/46910/… про мінуси.
Вадзім

@Vadzim Більшість "мінусів" - окрім відсутності документації / специфікації - звучать як BS !.
користувач2864740

28

Еквіваленти SQL Server функціям DEC2HEX, HEX2DEC на основі рядків Excel:

--Convert INT to hex string:
PRINT CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), 16777215),2) --DEC2HEX

--Convert hex string to INT:
PRINT CONVERT(INT,CONVERT(VARBINARY(4),'00FFFFFF',2)) --HEX2DEC


13

Це можливо за допомогою функції FORMAT, доступної на SQL Server 2012 і вище

select FORMAT(10,'x2')

Призводить до:

0a

5

Традиційний 4-бітний шістнадцятковий код досить прямий. Шістнадцятковий рядок у ціле число (припускаючи, що значення зберігається у полі, що називається FHexString):

CONVERT(BIGINT,CONVERT(varbinary(4),
                (SELECT master.dbo.fn_cdc_hexstrtobin(

                    LEFT(FMEID_ESN,8)                       
                ))
                ))

Ціле число до шістнадцяткового рядка (припускаючи, що значення зберігається у полі, що називається FInteger):

(SELECT master.dbo.fn_varbintohexstr(CONVERT(varbinary,CONVERT(int,
                    FInteger
                ))))

Важливо зазначити, що коли ви починаєте використовувати бітові розміри, які спричиняють спільний доступ до регістрів, особливо на машині Intel, ваші високі та низькі та ліві та права в регістрах будуть помінені місцями через незначну природу Intel. Наприклад, коли використовується varbinary (3), ми говоримо про 6-символьну шістнадцяткову форму. У цьому випадку ваші біти поєднуються як такі індекси справа наліво "54,32,10". В системі Intel ви очікували б "76,54,32,10". Оскільки ви використовуєте лише 6 з 8, вам слід пам’ятати, що робити заміни потрібно самостійно. "76,54" вважатиметься вашим лівим, а "32,10" - вашим правим. Кома розділяє ваш високий і низький. Intel міняє місцями максимуми і мінімуми, потім ліворуч і праворуч. Отже, щоб зробити перетворення ... зітхайте, ви повинні поміняти їх місцями, наприклад,

(SELECT master.dbo.fn_replvarbintoint(
                CONVERT(varbinary(3),(SELECT master.dbo.fn_cdc_hexstrtobin(
                    --intel processors, registers are switched, so reverse them 


                    ----second half
                    RIGHT(FHex8,2)+ --0,1 (0 indexed)
                    LEFT(RIGHT(FHex8,4),2)+ -- 2,3 (oindex)
                    --first half
                    LEFT(RIGHT(FHex8,6),2) --4,5

                )))
                ))

Це дещо складно, тому я намагався б зберегти свої перетворення в 8 символьних шістнадцяткових символів (varbinary (4)).

Таким чином, це має відповісти на ваше запитання. Всебічно.


5

Ось функція для SQL-сервера, яка перетворює цілочисельне значення у його шістнадцяткове представлення як varchar. Це має бути легко адаптуватися до інших типів баз даних

Наприклад:

SELECT dbo.ToHex(4095) --> FFF

SQL:

CREATE FUNCTION ToHex(@value int)
RETURNS varchar(50)
AS
BEGIN
    DECLARE @seq char(16)
    DECLARE @result varchar(50)
    DECLARE @digit char(1)
    SET @seq = '0123456789ABCDEF'

    SET @result = SUBSTRING(@seq, (@value%16)+1, 1)

    WHILE @value > 0
    BEGIN
        SET @digit = SUBSTRING(@seq, ((@value/16)%16)+1, 1)

        SET @value = @value/16
        IF @value <> 0 SET @result = @digit + @result
    END 

    RETURN @result
END
GO

Це працює! Ідеально! Вам просто потрібно замінити "IF @ value 0" на "IF @ value <> 0"
M07

Мені подобається це рішення, оскільки воно легко модифікується на ще більш потужне. Я подав такий приклад рішення використання довжини послідовності як основи.
Грег

3

Використовуйте master.dbo.fnbintohexstr(16777215)для перетворення у varcharподання.


1
select master.sys.fn_varbintohexstr(1)у 2008 році
еккіс

2
Declare @Dato xml
Set @Dato = Convert(xml, '<dato>FF</dato>')
Select Cast( rw.value( 'xs:hexBinary( text()[1])' , 'varbinary(max)' ) as int ) From @Dato.nodes('dato') as T(rw)

2

Відповідь Максима Козленка приємний і може бути дещо змінений для обробки кодування числового значення до будь-якого формату коду. Наприклад:

CREATE FUNCTION [dbo].[IntToAlpha](@Value int)
RETURNS varchar(30)
AS
BEGIN
    DECLARE @CodeChars varchar(100) 
    SET @CodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    DECLARE @CodeLength int = 26
    DECLARE @Result varchar(30) = ''
    DECLARE @Digit char(1)

    SET @Result = SUBSTRING(@CodeChars, (@Value % @CodeLength) + 1, 1)
    WHILE @Value > 0
    BEGIN
        SET @Digit = SUBSTRING(@CodeChars, ((@Value / @CodeLength) % @CodeLength) + 1, 1)
        SET @Value = @Value / @CodeLength
        IF @Value <> 0 SET @Result = @Digit + @Result
    END 

    RETURN @Result
END

Отже, така велика кількість, як 150 мільйонів, стає лише 6 символами (150 000 000 = "MQGJMU")

Ви також можете використовувати різні символи в різних послідовностях як пристрій для шифрування. Або передайте символи коду та довжину символів і використовуйте як метод соління для шифрування.

І навпаки:

CREATE FUNCTION [dbo].[AlphaToInt](@Value varchar(7))
RETURNS int
AS
BEGIN
    DECLARE @CodeChars varchar(100) 
    SET @CodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    DECLARE @CodeLength int = 26
    DECLARE @Digit char(1)
    DECLARE @Result int = 0
    DECLARE @DigitValue int
    DECLARE @Index int = 0
    DECLARE @Reverse varchar(7)
    SET @Reverse = REVERSE(@Value)

    WHILE @Index < LEN(@Value)
    BEGIN
        SET @Digit = SUBSTRING(@Reverse, @Index + 1, 1)
        SET @DigitValue = (CHARINDEX(@Digit, @CodeChars) - 1) * POWER(@CodeLength, @Index)
        SET @Result = @Result + @DigitValue
        SET @Index = @Index + 1
    END 
    RETURN @Result

2

Максим Козленко має гарне рішення, і інші наближаються до того, щоб розкрити весь його потенціал, але потім повністю пропускають, зрозумівши, що ви можете визначити будь-яку послідовність символів і використовувати його довжину як основу . Ось чому мені подобається ця трохи модифікована версія його рішення, оскільки вона може працювати для бази 16, або бази 17 і т.д.

Наприклад, що робити, якщо ви хотіли букви та цифри, але не подобається I, що я схожий на одиниці, а O - як 0. Ви можете визначити будь-яку послідовність таким чином. Нижче наведена форма "Основи 36", яка пропускає I і O, щоб створити "модифіковану основу 34". Скасуйте коментар шістнадцяткового рядка, а не виконайте його як шістнадцятковий.

declare @value int = 1234567890

DECLARE @seq varchar(100) = '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ' -- modified base 34
--DECLARE @seq varchar(100) = '0123456789ABCDEF' -- hex
DECLARE @result varchar(50)
DECLARE @digit char(1)
DECLARE @baseSize int = len(@seq)
DECLARE @workingValue int = @value

SET @result = SUBSTRING(@seq, (@workingValue%@baseSize)+1, 1)

WHILE @workingValue > 0
BEGIN
    SET @digit = SUBSTRING(@seq, ((@workingValue/@baseSize)%@baseSize)+1, 1)

    SET @workingValue = @workingValue/@baseSize
    IF @workingValue <> 0 SET @result = @digit + @result
END 

select @value as Value, @baseSize as BaseSize, @result as Result

Значення, розмір бази, результат

1234567890, 34, T5URAA

Я також перемістив значення до робочого значення, а потім працюю з копії робочого значення, як особисті уподобання.

Нижче наведено додаткове для зворотного перетворення для будь-якої послідовності, з основою, визначеною як довжина послідовності.

declare @value varchar(50) = 'T5URAA'

DECLARE @seq varchar(100) = '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ' -- modified base 34
--DECLARE @seq varchar(100) = '0123456789ABCDEF' -- hex
DECLARE @result int = 0
DECLARE @digit char(1)
DECLARE @baseSize int = len(@seq)
DECLARE @workingValue varchar(50) = @value

DECLARE @PositionMultiplier int = 1
DECLARE @digitPositionInSequence int = 0

WHILE len(@workingValue) > 0
BEGIN
    SET @digit = right(@workingValue,1)
    SET @digitPositionInSequence = CHARINDEX(@digit,@seq)
    SET @result = @result + ( (@digitPositionInSequence -1) * @PositionMultiplier)

    --select @digit, @digitPositionInSequence, @PositionMultiplier, @result

    SET @workingValue = left(@workingValue,len(@workingValue)-1)
    SET @PositionMultiplier = @PositionMultiplier * @baseSize
END 

select @value as Value, @baseSize as BaseSize, @result as Result

1

Дано:

declare @hexStr varchar(16), @intVal int

IntToHexStr:

select @hexStr = convert(varbinary, @intVal, 1)

HexStrToInt:

declare
    @query varchar(100),
    @parameters varchar(50)

select
    @query = 'select @result = convert(int,' + @hb + ')',
    @parameters = '@result int output'

exec master.dbo.Sp_executesql @query, @parameters, @intVal output

0
IIF(Fields!HIGHLIGHT_COLOUR.Value="","#FFFFFF","#" & hex(Fields!HIGHLIGHT_COLOUR.Value) & StrDup(6-LEN(hex(Fields!HIGHLIGHT_COLOUR.Value)),"0"))

Працює для мене як вираз у кольорі шрифту


0

Щоб перетворити шістнадцяткові рядки в INT, я використовував це раніше. Його можна змінити, щоб перетворити будь-яку базу на INT фактично (восьмеричну, двійкову, що завгодно)

Declare @Str varchar(200)
Set @str = 'F000BE1A'

Declare @ndx int
Set @ndx = Len(@str)
Declare @RunningTotal  BigInt
Set @RunningTotal = 0

While @ndx > 0
Begin
    Declare @Exponent BigInt
    Set @Exponent = Len(@Str) - @ndx

    Set @RunningTotal = @RunningTotal + 

    Power(16 * 1.0, @Exponent) *
    Case Substring(@str, @ndx, 1)
        When '0' then 0
        When '1' then 1
        When '2' then 2 
        When '3' then 3
        When '4' then 4
        When '5' then 5
        When '6' then 6
        When '7' then 7
        When '8' then 8
        When '9' then 9
        When 'A' then 10
        When 'B' then 11
        When 'C' then 12
        When 'D' then 13
        When 'E' then 14
        When 'F' then 15
    End
    Set @ndx = @ndx - 1
End

Print @RunningTotal

0

Нижче наведено дві функції: dbo.HexToInt і dbo.IntToHex, я використовую їх для такого перетворення:

if OBJECT_ID('dbo.HexToInt') is not null
    drop function dbo.HexToInt
GO
create function dbo.HexToInt (@chars varchar(max))
returns int
begin
    declare @char varchar(1), @len int, @i int, @r int, @tmp int, @pow int
    set @chars = RTRIM(LTRIM(@chars))
    set @len = LEN(@chars)
    set @i = 1
    set @r = 0
    while @i <= @len
    begin
        set @pow = @len - @i
        set @char = SUBSTRING(@chars, @i, 1)
        if @char = '0'
            set @tmp = 0
        else if @char = '1'
            set @tmp = 1
        else if @char = '2'
            set @tmp = 2
        else if @char = '3'
            set @tmp = 3
        else if @char = '4'
            set @tmp = 4
        else if @char = '5'
            set @tmp = 5
        else if @char = '6'
            set @tmp = 6
        else if @char = '7'
            set @tmp = 7
        else if @char = '8'
            set @tmp = 8
        else if @char = '9'
            set @tmp = 9
        else if @char = 'A'
            set @tmp = 10
        else if @char = 'B'
            set @tmp = 11
        else if @char = 'C'
            set @tmp = 12
        else if @char = 'D'
            set @tmp = 13
        else if @char = 'E'
            set @tmp = 14
        else if @char = 'F'
            set @tmp = 15
        set @r = @r + @tmp * POWER(16,@pow)
        set @i = @i + 1     
    end
    return @r
end

І другий:

if OBJECT_ID('dbo.IntToHex') is not null
    drop function dbo.IntToHex
GO
create function dbo.IntToHex (@val int)
returns varchar(max)
begin
    declare @r varchar(max), @tmp int, @v1 int, @v2 int, @char varchar(1)
    set @tmp = @val
    set @r = ''
    while 1=1
    begin
        set @v1 = @tmp / 16
        set @v2 = @tmp % 16
        if @v2 = 0
            set @char = '0'
        else if @v2 = 1
            set @char = '1'
        else if @v2 = 2
            set @char = '2'
        else if @v2 = 3
            set @char = '3'
        else if @v2 = 4
            set @char = '4'
        else if @v2 = 5
            set @char = '5'
        else if @v2 = 6
            set @char = '6'
        else if @v2 = 7
            set @char = '7'
        else if @v2 = 8
            set @char = '8'
        else if @v2 = 9
            set @char = '9'
        else if @v2 = 10
            set @char = 'A'
        else if @v2 = 11
            set @char = 'B'
        else if @v2 = 12
            set @char = 'C'
        else if @v2 = 13
            set @char = 'D'
        else if @v2 = 14
            set @char = 'E'
        else if @v2 = 15
            set @char = 'F'
        set @tmp = @v1 
        set @r = @char + @r
        if @tmp = 0
            break
    end
    return @r
end
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.