Convert signed int to string ip address in SQL Server

旧城冷巷雨未停 提交于 2019-12-04 10:09:35
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)

The code you have would work if IPADDRESS was a bigint (effectively storing the unsigned int representation in the database - i.e. all values > 0). Do you have the option of changing the datatype in the table?

To get what you have to work, you need to convert your signed int to the equivalent unsigned int before the conversion to bigint. I'm not sure what the most efficient way to do this in TSQL is, but it might be to cast it to binary:

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
CaMiX

Like @Ed Harper stated that the selected solution doesn't work for a signed int. Below is my solution which requires a little less casting and isn't inverted. Check out the following test scenario shown below where the converted string/varchar IP should be 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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!