Need to move some code from MySql to TSql. I have a couple of calls to INET_ATON which converts a string which resembles an IPAddress into a number. Is there a T-SQL equival
An abuse of the parsname function:
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
That "short form address" thing is not supported here though.
Little better. It uses int (4b) instead of bigint (8b). Your result should only be four bytes... one per octet:
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;
Here's a function to convert an IP address to a string:
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
After creating the function, you can call it like:
select dbo.IpToString('1.2.3.4')
More a different option than a direct answer to your question (I see the downvotes coming ^^), but you could also consider putting the conversion logic into your software instead of the query. Depending on language and use case this might be even better.
PHP: ip2long("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;
You could also give it -1
, or null
(with long?
as datatype), or write a method which throws an exception, in case the conversion fails.
Python
reduce(lambda sum, chunk: sum <<8 | chunk, map(int, '192.168.1.1'.split(".")))
Before you start downvoting: This is just a short example, no error handling here, I know.
Of course it is most of the time nicer to let the dbs do the job, but it really depends, and in case you don' t have a project with millions of requests per second, this might help.