将signed int转换为SQL Server中的字符串IP地址

时间:2012-06-24 12:54:28

标签: sql-server ip-address

我正在从SQL Server数据库中检索已签名的int,需要将其转换为“正常”的点缀字符串,以便向用户显示。

谷歌搜索,我找到了这段代码:

SELECT 
   dbo.IPADDRESS.IPADDRESS,
   CAST(ROUND( (cast(dbo.IPADDRESS.IPADDRESS as bigint) / 16777216 ), 0, 1) AS varchar(4)) + '.' +
   CAST((ROUND( (cast(dbo.IPADDRESS.IPADDRESS as bigint) / 65536 ), 0, 1) % 256) AS varchar(4)) + '.' +
   CAST((ROUND( (cast(dbo.IPADDRESS.IPADDRESS as bigint) / 256 ), 0, 1) % 256) AS varchar(4)) + '.' + 
   CAST((cast(dbo.IPADDRESS.IPADDRESS as bigint) % 256 ) AS varchar(4)) as IPDottedNotation
FROM  
   dbo.IPADDRESS

在某些时候有效,但有时会产生古怪的输出。例如,转换此-1951276725会产生结果-116.-78.-30.-181

有什么建议吗?感谢。

3 个答案:

答案 0 :(得分:9)

DECLARE @IPADDRESS TABLE (
  IPADDRESS INT);

INSERT INTO @IPADDRESS
VALUES      (-1139627840),
            ( 1);

SELECT 
        LTRIM(CAST(SUBSTRING(IP,4,1) AS TINYINT)) + '.' + 
        LTRIM(CAST(SUBSTRING(IP,3,1) AS TINYINT)) + '.' + 
        LTRIM(CAST(SUBSTRING(IP,2,1) AS TINYINT)) + '.' + 
        LTRIM(CAST(SUBSTRING(IP,1,1) AS TINYINT))
FROM @IPADDRESS
CROSS APPLY (SELECT CAST(IPADDRESS AS BINARY(4))) C(IP)

enter image description here

答案 1 :(得分:3)

如果IPADDRESS是bigint(有效地将unsigned int表示存储在数据库中 - 即所有值> 0),那么您所拥有的代码将起作用。您是否可以选择更改表中的数据类型?

要获得必须工作的内容,您需要在转换为bigint之前将signed int转换为等效的unsigned int。我不确定在TSQL中执行此操作的最有效方法是什么,但可能是将其转换为二进制文件:

SELECT dbo.IPADDRESS.IPADDRESS,
CAST(ROUND( (cast(cast(dbo.IPADDRESS.IPADDRESS as binary(4)) as bigint) / 16777216 ), 0, 1) AS varchar(4)) + '.' +
CAST((ROUND( (cast(cast(dbo.IPADDRESS.IPADDRESS as binary(4)) as bigint) / 65536 ), 0, 1) % 256) AS varchar(4)) + '.' +
CAST((ROUND( (cast(cast(dbo.IPADDRESS.IPADDRESS as binary(4)) as bigint) / 256 ), 0, 1) % 256) AS varchar(4)) + '.' + 
CAST((cast(cast(dbo.IPADDRESS.IPADDRESS as binary(4)) as bigint) % 256 ) AS varchar(4)) as IPDottedNotation

答案 2 :(得分:1)

与@Ed一样,Harper表示所选解决方案不适用于signed int。以下是我的解决方案,需要少一点铸造而不是倒置。查看下面显示的以下测试场景,其中转换后的字符串/ varchar IP应为192.168.18.188:

CREATE TABLE #data
  (
     ip     NVARCHAR(45),
     before NVARCHAR(45)
  )

INSERT INTO #data
VALUES     ('converted-ip','-1139627840')

    update #data
    set ip = cast((cast(before as int) & 255) as nvarchar) + '.' +
         cast((cast(floor(convert(decimal, before)/256) as int) & 255) as nvarchar) + '.' +
         cast((cast(floor(convert(decimal, before)/65536) as int) & 255) as nvarchar) + '.' +
         cast((cast(floor(convert(decimal, before)/16777216) as int) & 255) as nvarchar)

select * from #data