将整数转换为十六进制,以及将十六进制转换为整数。

80

我已经在Sybase中使这个查询(其中signal_data是一列)工作了,但在Microsoft SQL Server中它不起作用:

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

我也有它的Excel版本(其中A1包含此值):

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

有人知道我该如何在SQL Server中完成这个操作吗?

16个回答

133

将 INT 转换为十六进制:

SELECT CONVERT(VARBINARY(8), 16777215)

将十六进制转换为整数:

SELECT CONVERT(INT, 0xFFFFFF)

更新 2015-03-16

上面的示例只有在十六进制值以整数文字形式给出时才有效。为完整起见,如果要转换的值是十六进制字符串(例如在 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将以十六进制值形式给出数据。不能对其进行字符串操作。 - fr21
1
@Bill Karwin,Pavan是正确的。Sql Server 2008可以通过convert函数实现,但2005及以下版本无法实现。 - Ben
2
当使用8字符十六进制,例如 ARGB 转换为 BIGINT 而不是 INT。 INT 的最大值仅为 2,147,483,647 或 7FFFFFFF。注意使用 INT 时,回转到十六进制的结果将有效,但是结果与 Excel 的 Hex2Dec 不同。 - DenverJT
SELECT CONVERT(INT, CONVERT(varbinary, '01', 2)) 返回 12337 (SQL Server 2005) - Ian Boyd
第一个示例不是转换为十六进制:它们转换为二进制。(二进制值独立于任何数字基础存在:数字基础只在字符串表示的上下文中有意义。) (此外,参数不一定要是文字(尽管必须是整数)。) 它们可能看起来像是转换为十六进制,因为当将二进制转换为字符串(例如显示它)时,默认情况下会用十六进制表示它。(这可以用于转换为十六进制,如@KipBryan的答案所示,但DenNukem和wndproc的答案更简单。) - John B. Lambe

49

实际上,内置函数的名称是master.dbo.fn_varbintohexstr。

因此,例如:

SELECT 100, master.dbo.fn_varbintohexstr(100)

给你

100 0x00000064


3
请参阅 http://dba.stackexchange.com/questions/46910/sys-fn-varbintohexstr-returns-null-if-varbinary-data-is-more-then-2000-as-datale 以了解这个函数的缺点。 - Vadzim
@Vadzim 大部分的“缺点” - 除了缺乏文档/规范之外 - 听起来都像胡说八道! - user2864740

32

SQL Server中与Excel基于字符串的DEC2HEX、HEX2DEC函数相对应的函数:

--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

25

在 SQL Server 2012 及以上版本中,可以使用可用的 FORMAT 函数。

select FORMAT(10,'x2')

结果为:

0a

19

将整数转换为十六进制:

SELECT FORMAT(512+255,'X')


1
自SQL Server 2012以来:https://msdn.microsoft.com/zh-cn/library/hh213505.aspx - Vadzim
1
'X' 的情况决定了十六进制输出的大小写。已点赞。 - Yogi

6
传统的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
                ))))

需要注意的是,当您开始使用导致寄存器共享的位大小时,特别是在英特尔机器上,由于英特尔的小端性质,您寄存器中的高低位和左右位将会被交换。例如,使用varbinary(3)时,我们谈论的是一个6个字符的十六进制数。在这种情况下,您的位被配对为从右到左的以下索引“54,32,10”。在英特尔系统中,您期望的是“76,54,32,10”。由于您仅使用了8位中的6位,因此需要记住自己进行交换。“76,54”将作为您的左侧,“32,10”将作为您的右侧。逗号分隔您的高低位。英特尔交换高低位,然后交换左右位。因此,要进行转换...哎呀,您必须自己交换它们,例如,以下内容将前6个8个字符的十六进制数进行转换:
(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

这里是将整数值转换为其十六进制表示形式的varchar的SQL Server函数。它应该很容易适应其他数据库类型。

例如:

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
我喜欢这个解决方案,因为它可以轻松地修改成更强大的解决方案。我提供了一个使用序列长度作为基础的示例解决方案。 - Greg

3

使用 master.dbo.fnbintohexstr(16777215) 来将其转换为 varchar 表示。


1
在2008中,选择master.sys.fn_varbintohexstr(1) - ekkis

3
Maksym Kozlenko提供了一个不错的解决方案,其他人也接近于充分发挥其潜力,但却完全没有意识到您可以定义任何字符序列,并将其长度作为基数。这就是为什么我喜欢他的解决方案的稍作修改版,因为它可以适用于16进制、17进制等。

例如,如果您想要字母和数字,但不喜欢I看起来像1,O看起来像0。您可以通过这种方式定义任何序列。以下是跳过I和O创建“修改后的基础34”的“基础36”表单。取消注释十六进制行以运行为十六进制。

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

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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接