What are the various ways to convert a varchar iPv4 Address into a number without using PARSENAME()
(non-deterministic) function in SQL Server, in order to create a persisted calculated column?
I used the string manipulation technique from Extract part of string based on nth instance of character to create the following:
Query
select
((256*256*256)*convert(bigint, ltrim(rtrim(substring(replace('255.255.255.255','.',replicate(' ',8)),1, 9)))))
+
((256*256)*convert(bigint,ltrim(rtrim(substring(replace('255.255.255.255','.',replicate(' ',8)),10, 9)))))
+
((256)*convert(bigint,ltrim(rtrim(substring(replace('255.255.255.255','.',replicate(' ',8)),19, 9)))))
+
(convert(bigint,ltrim(rtrim(substring(replace('255.255.255.255','.',replicate(' ',8)),28, 9)))))
Here is a visual of what the string manipulation looks like before each segment is converted to BIGINT and multiplied:
… This works to create a deterministic calculated column that can be persisted. What other more efficient techniques are there out there?
Best Answer
One option is to use SQLCLR. It is rather easy to create a method to split the string on the periods, convert each to an
Int64
, and multiply by the appropriate power of 256. Be sure to setIsDeterministic=true
in theSqlFunction
attribute, which will not only allow it to be persisted, but will also allow it to participate in parallel plans :-). And in fact, the SQL# SQLCLR library (that I created) contains functions (which are in the Free version) to do this conversion: INET_AddressToNumber and INET_NumberToAddress.Test Setup:
Regarding the following three tests, please note:
SELECT
several times and kept the best time for each, not average time.SQLCLR Test and Results:
MartinSmith's Test and Results:
O.P.'s Test and Results:
One thing to keep in mind regarding the SQLCLR option: using a SQLCLR function in a computed column is a dependency that will prevent the Assembly containing the function from being dropped. If you are able to use
ALTER ASSEMBLY
, then you won't being dropping and re-creating the Assembly. ButALTER ASSEMBLY
is only allowed if there are no new or removed methods, and if the signatures of existing methods are still the same. If any of those changes are being made, then you will have to drop the Assembly and then create it again. And that will require that you first drop the computed column that is referencing the SQLCLR function contained in that Assembly. This might make the SQLCLR option less desirable in the use case of placing a function in a computed column, whereas if the function was in a query, Stored Procedure, View, etc, then this wouldn't be a concern.It is possible to wrap the SQLCLR function in a T-SQL function and reference the T-SQL function in the computed column, but then you lose the benefit of SQLCLR functions being able to participate a parallel execution plan.