Sql server 在SQL Server中将签名int转换为字符串ip地址

Sql server 在SQL Server中将签名int转换为字符串ip地址,sql-server,ip-address,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.I

我正在从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


有什么建议吗?谢谢。

如果
IPADDRESS
是一个bigint(有效地将未签名的int表示形式存储在数据库中,即所有值>0),那么您的代码就可以工作了。您可以选择更改表中的数据类型吗

要获得所需的工作,需要在转换为bigint之前将有符号int转换为等效的无符号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

像@Ed Harper所说的那样,所选的解决方案对于带符号的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

我是一个MSSQL新手,我正在努力理解这里发生了什么。有人愿意“告诉”我吗。@jalperin在
交叉应用中
将4字节整数转换为4字节二进制。然后,该表达式的结果被别名为
IP
。这只是为了避免需要对二进制文件重复四次强制转换。
子字符串(IP,1,1)
从中提取第一个字节,
子字符串(IP,2,1)
第二个字节,依此类推。这将在
0x00
0xFF
的范围内,转换为
tinyint
将其转换为十进制形式。
LTRIM
用于将结果强制转换为字符串,以便将其连接在一起形成虚线形式。比
CAST(CAST(子字符串(IP,1,1)作为TINYINT)作为VARCHAR(3))更简洁
@MartinSmith伟大的解释;非常感谢。还有一点:那么整个语句可以插入我的实际SELECT?(我习惯于使用表名,因此使用列名让我感到困惑。)@jalperin-是的,dbo.IPADDRESS中的
是对实际表的引用。
CROSS APPLY
中的
SELECT
引用了该列。此解决方案不适用于负/有符号整数ip值。在我的示例中,ip字节由于某种原因会反转,但没有问题。效果很好
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