【问题标题】:Porting from MySql to T-Sql. Any INET_ATON() equivalent?从 MySql 移植到 T-Sql。任何 INET_ATON() 等价物?
【发布时间】:2010-10-16 06:50:05
【问题描述】:

需要将一些代码从 MySql 移动到 TSql。我有几个对 INET_ATON 的调用,它将一个类似于 IPAddress 的字符串转换为一个数字。是否有等效的 T-SQL?

【问题讨论】:

    标签: sql mysql tsql


    【解决方案1】:

    parsname 函数的滥用:

    create function INET_ATON (@addr varchar(15))
    returns bigint
    with schemabinding
    as
    begin
      return  
        cast(parsename(@addr, 4) as bigint) * 16777216 +
        cast(parsename(@addr, 3) as bigint) * 65536 +
        cast(parsename(@addr, 2) as bigint) * 256 +
        cast(parsename(@addr, 1) as bigint)
    end
    

    这里不支持“短格式地址”。

    【讨论】:

      【解决方案2】:

      这是一个将 IP 地址转换为字符串的函数:

      CREATE FUNCTION dbo.IpToString 
          (@ip_str VarChar(15))
      returns BigInt
      as
          begin
          declare @i int
          declare @dot_pos int
          declare @current_part VarChar(15)
          declare @result BigInt
      
          set @result = 0
          set @i = 0
      
          while Len(@ip_str) > 0
              begin
              set @i = @i + 1
              set @dot_pos = CharIndex('.', @ip_str)
              if @dot_pos > 0
                  begin
                  set @current_part = Left(@ip_str, @dot_pos - 1)
                  set @ip_str = SubString(@ip_str, @dot_pos + 1, 15)
                  end
              else 
                  begin
                  set @current_part = @ip_str
                  set @ip_str = ''
                  end
      
              if Len(@current_part) > 3 Return(Null)
              if IsNumeric(@current_part) = 0 Return (Null)
              if not cast(@current_part as int) between 0 and 255 Return (Null)
              set @result = 256 * @result + Cast(@current_part as BigInt)
              end
      
          if @i = 4 Return(@result)
      
          Return(Null)
          end
      

      创建函数后,可以这样调用:

      select dbo.IpToString('1.2.3.4')
      

      【讨论】:

        【解决方案3】:

        稍微好一点。它使用 int (4b) 而不是 bigint (8b)。您的结果应该只有四个字节......每个八位字节一个:

        create function INET_ATON (@ip varchar(15))
        returns int
        begin
            declare @rslt int 
            -- This first part is a little error checking
            -- Looks for three dots and all numbers when not dots 
            if len(@ip) - len(replace(@ip,'.','')) = 3 
                AND
                    isnumeric(replace(@ip,'.','')) = 1
            begin 
            set @rslt = convert(int,
                    convert(binary(1),convert(tinyint,parsename(@ip, 4)))
                +   convert(binary(1),convert(tinyint,parsename(@ip, 3)))
                +   convert(binary(1),convert(tinyint,parsename(@ip, 2)))
                +   convert(binary(1),convert(tinyint,parsename(@ip, 1)))
                )
            end
            else set @rslt = 0
            return @rslt
        end;
        

        【讨论】:

          【解决方案4】:

          与直接回答您的问题相比,这是一个不同的选择(我看到了反对票 ^^),但您也可以考虑将转换逻辑放入您的软件而不是查询中。根据语言和用例,这可能会更好。

          示例

          PHPip2long("192.168.1.1");

          C/C++inet_addr("192.168.1.1");

          C#

          System.Net.IPAddress ip;
          long ipn = (System.Net.IPAddress.TryParse("192.168.1.1", out ip))
          
              ? (((long) ip.GetAddressBytes()[0] << 24) | (ip.GetAddressBytes()[1] << 16) |
                        (ip.GetAddressBytes()[2] <<  8) |  ip.GetAddressBytes()[3])
          
              : 0;
          

          你也可以给它-1,或者null(以long?作为数据类型),或者写一个抛出异常的方法,以防转换失败。

          Python

          reduce(lambda sum, chunk: sum <<8 | chunk, map(int, '192.168.1.1'.split(".")))
          

          在你开始投票之前:这只是一个简短的例子,我知道这里没有错误处理。

          结论

          当然,大多数时候让 dbs 完成这项工作会更好,但这确实取决于,如果您没有每秒处理数百万个请求的项目,这可能会有所帮助。

          【讨论】:

            猜你喜欢
            • 2010-11-10
            • 2020-03-28
            • 2012-05-10
            • 1970-01-01
            • 2010-11-09
            • 2011-12-08
            • 2010-09-27
            • 2010-11-27
            • 2010-10-20
            相关资源
            最近更新 更多