我正在从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
。
有什么建议吗?感谢。
答案 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)
答案 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