2010-09-08 105 views
8

我们使用二进制(16)字段来存储IP地址。我们这样做,因为它可以同时拥有IPv4和IPv6地址,并且很容易与.Net IPAddress类一起使用。完善SQL二进制到IP地址字符串转换

但是,为了报告目的,我创建了以下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 = 'ABCDEF' 

     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地址。这是一个安全的假设吗?检查所有剩余字节为零还是有更好的方法更好?

编辑去除不必要的投

回答

5

我说你应该被存储的地址族也,在您的字节数组或一个单独的列无论是编码。如果将16个字节传递给IPAddress构造函数,它将构造为IPv6地址,因此您需要在代码中检查以确定地址族。看起来似乎更容易(并且不依赖于对IPv6地址字节的假设)直接保留这些信息。

或者使用VARBINARY(16),然后你就可以检查(长度= 4 => IPv4地址)

+0

很好的建议,谢谢你的长度。 – Magpie 2010-09-08 09:13:01

相关问题