完善SQL二进制到IP地址字符串转换(Perfecting SQL binary to IP Address string conversion)
我们使用二进制(16)字段来存储IP地址。 我们这样做,因为它可以同时拥有IPv4和IPv6地址,并且很容易与.Net IPAddress类一起使用。
但是,为了报告目的,我创建了以下SQL函数将二进制地址转换为IP地址字符串。
CREATE FUNCTION fn_ConvertBinaryIPAddressToString ( @binaryIP binary(16) ) RETURNS nvarchar(39) AS BEGIN DECLARE @ipAsString nvarchar(39) -- Is IPv4 IF (substring(@binaryIP, 5, 1) = 0x00) <-- Is there a better way? BEGIN SELECT @ipAsString = CAST(CAST(substring(@binaryIP, 1, 1) AS int) AS nvarchar(3)) + '.' + CAST(CAST(substring(@binaryIP, 2, 1) AS int) AS nvarchar(3)) + '.' + CAST(CAST(substring(@binaryIP, 3, 1) AS int) AS nvarchar(3)) + '.' + CAST(CAST(substring(@binaryIP, 4, 1) AS int) AS nvarchar(3)) END ELSE BEGIN -- Is IPv6 -- taken and modified from http://support.microsoft.com/kb/104829 DECLARE @i int DECLARE @length int DECLARE @hexstring char(16) SELECT @ipAsString = '' SELECT @i = 1 SELECT @length = 16 SELECT @hexstring = '0123456789ABCDEF' WHILE (@i <= @length) BEGIN DECLARE @tempint int DECLARE @firstint int DECLARE @secondint int SELECT @tempint = convert(int, substring(@binaryIP,@i,1)) SELECT @firstint = floor(@tempint/16) SELECT @secondint = @tempint - (@firstint*16) SELECT @ipAsString = @ipAsString + substring(@hexstring, @firstint+1, 1) + substring(@hexstring, @secondint+1, 1) IF (@i % 2 = 0) SELECT @ipAsString = @ipAsString + ':' SELECT @i = @i + 1 END END -- Return the result of the function RETURN @ipAsString END GO
此刻如果5字节是0,我认为它是一个IPv4地址。 这是一个安全的假设吗? 检查所有剩余字节为零还是有更好的方法更好?
编辑删除不必要的演员
We use a binary(16) field to store IP Addresses. We do this as it can hold both IPv4 and IPv6 addresses and is easily used with the .Net IPAddress class.
However I have created the following SQL function to convert the binary address to the IP Address string for reporting purposes.
CREATE FUNCTION fn_ConvertBinaryIPAddressToString ( @binaryIP binary(16) ) RETURNS nvarchar(39) AS BEGIN DECLARE @ipAsString nvarchar(39) -- Is IPv4 IF (substring(@binaryIP, 5, 1) = 0x00) <-- Is there a better way? BEGIN SELECT @ipAsString = CAST(CAST(substring(@binaryIP, 1, 1) AS int) AS nvarchar(3)) + '.' + CAST(CAST(substring(@binaryIP, 2, 1) AS int) AS nvarchar(3)) + '.' + CAST(CAST(substring(@binaryIP, 3, 1) AS int) AS nvarchar(3)) + '.' + CAST(CAST(substring(@binaryIP, 4, 1) AS int) AS nvarchar(3)) END ELSE BEGIN -- Is IPv6 -- taken and modified from http://support.microsoft.com/kb/104829 DECLARE @i int DECLARE @length int DECLARE @hexstring char(16) SELECT @ipAsString = '' SELECT @i = 1 SELECT @length = 16 SELECT @hexstring = '0123456789ABCDEF' WHILE (@i <= @length) BEGIN DECLARE @tempint int DECLARE @firstint int DECLARE @secondint int SELECT @tempint = convert(int, substring(@binaryIP,@i,1)) SELECT @firstint = floor(@tempint/16) SELECT @secondint = @tempint - (@firstint*16) SELECT @ipAsString = @ipAsString + substring(@hexstring, @firstint+1, 1) + substring(@hexstring, @secondint+1, 1) IF (@i % 2 = 0) SELECT @ipAsString = @ipAsString + ':' SELECT @i = @i + 1 END END -- Return the result of the function RETURN @ipAsString END
GO
At the moment if the 5 byte is 0 I assume it is an IPv4 address. Is this a safe assumption? Is it better to check all the remaining bytes for zeros or is there a better way?
EDIT removed unnecessary cast