N S

Novick Software Management • Design • Programming • Training • Consulting

   

 

 

SQL Server T-SQL User-Defined Function of the Week

Convert Bit Strings Back to Integers

Volume 1 Number 26      May 27, 2003

Sign up for this newsletter at:
http://www.novicksoftware.com/UdfOfWeek/UDFofWeekSignup.htm

Visit the T-SQL UDF of the Week at:
http://www.NovickSoftware.com/UdfOfWeek/UDFofWeek.htm

Check out the UDF Frequently Asked Questions at:
http://www.novicksoftware.com/UdfOfWeek/UDF_FAQ.htm

To ask a UDF related question or to contribute a UDF,
send e-mail to udf@NovickSoftware.com

Various functions and system tables use bit fields as a very 
compact way to store several bits in one int.  A few weeks ago 
Issue #23 discussed the undocumented system UDF
fn_replinttobitstring, which converts an int to a 32 character 
string of ones and zeros. This is usually done for human
consumption.  That newsletter also included udf_BitS_FromInt,
which does the same job as fn_replinttobitstring but can be 
more convenient because it strips leading zeros.

fn_replinttobitstring has a complementary function 
fn_replbitstringtoint, which is also an undocumented system UDF.
It's a scalar function with he syntax:

         fn_replbitstringtoint (@Bitstring)
         
@Bitstring is a 32-character string of 1s and 0s that represent
the bits of an integer.  For example:
'00000000000000000000000000000010' represents 2. 

This query shows some examples of fn_replbitstringtoint:
/------- Start copying below this line -------------------------\
-- examples of fn_replbitstringtoint
select fn_replbitstringtoint ('00000000000000000000000000000010') as [2]
     , fn_replbitstringtoint ('11111111111111111111111111111111') as [-1]
     , fn_replbitstringtoint ('10000000000000000000000000000000') 
                                        as [Most negative number]
     , fn_replbitstringtoint ('01111111111111111111111111111111') 
                                         as [Most positive number]
go
\-------Stop copying above this line ---------------------------/
(Results)
2           -1          Most negative number Most positive number 
----------- ----------- -------------------- ------------------- 
2           -1          -2147483648          2147483647

fn_replbitstringtoint doesn't handle missing leading zeros well.
In fact, it assumes that they're missing trailing zeros.  That's
not a very useful interpretation as shown in this query:
/------- Start copying below this line -------------------------\
-- what happens when there are missing leading zeros
select fn_replbitstringtoint ('00000000000000000000000000001100') as [12]
     , fn_replbitstringtoint ('1100') as [12 without leading zeros]
go 
\-------Stop copying above this line ---------------------------/
12          12 without leading zeros 
----------- ------------------------ 
12          -1073741824

The function udf_BitS_ToInt improves on fn_replbitstringtoint by 
padding with leading zeros before using fn_replbitstringtoint
to do the actual conversion.  Here's the CREATE FUNCTION script:
/------- Start copying below this line -------------------------\
SET QUOTED_IDENTIFIER ON 
GO
SET ANSI_NULLS ON 
GO

CREATE FUNCTION dbo.udf_BitS_ToInt (

    @BitString varchar(32) -- Bit pattern for the input
)   RETURNS int
    -- No SCHEMABINDING, uses system UDF
/*
* Converts a bit string of up to 32 characters into the 
* corresponding int.  The string is padded on the left with any
* missing zeros.
*
* Related Functions: the undocumented built-in function 
*         fn_replbitstringtoint is similar but does not handle
*         missing leading zeros the same way.
* Maintenance Notes: based on undocumented built-in function 
*          fn_replbitstringtoint, will have to change if it's 
*          behavior changes.
*
* Example:
SELECT dbo.udf_BitS_ToInt('1101') -- should return 13
*
* Test:
PRINT 'Test 1   13       ' + CASE WHEN 13 = 
  dbo.udf_BitS_ToInt ('1101') THEN 'Worked' ELSE 'ERROR' END
PRINT 'Test 2   -1       ' + CASE WHEN -1=dbo.udf_BitS_ToInt 
                        ('11111111111111111111111111111111')
                         THEN 'Worked' ELSE 'ERROR' END
PRINT 'Test 2 biggest int ' + CASE WHEN 2147483647=
  dbo.udf_BitS_ToInt ('01111111111111111111111111111111')
                     THEN 'Worked' ELSE 'ERROR' END
*
* © Copyright 2003 Andrew Novick http://www.NovickSoftware.com
* You may use this function in any of your SQL Server databases
* including databases that you sell, so long as they contain 
* other unrelated database objects. You may not publish this 
* UDF either in print or electronically.
* Published in the T-SQL UDF of the Week Vol 1 #26  May 13, 2003
http://www.NovickSofware.com/UDFofWeek/UDFofWeek.htm
****************************************************************/
AS BEGIN

    DECLARE @WorkingVariable int

    -- fn_replbitstringtoint is used but the argument is prepped 
    -- by padding with the correct number of leading zeros.
    SELECT @WorkingVariable = fn_replbitstringtoint (
                RIGHT('000000000000000000000000000000000000' 
                + @Bit String, 32))

    Return @WorkingVariable
END

GRANT EXECUTE  ON [dbo].[udf_BitS_ToInt]  TO [PUBLIC]
GO
\-------Stop copying above this line ---------------------------/

Lets look at a few calls to udf_BitS_ToInt and a comparison with
fn_replbitstringtoint:
/------- Start copying below this line -------------------------\
-- try out udf_BitS_ToInt and compare with fn_replbitstringtoint
SELECT 
  dbo.udf_BitS_ToInt ('11111111111111111111111111111111') as [-1]
     , dbo.udf_BitS_ToInt ('01111111111111111111111111111111') 
                                         as [Most positive num]
, dbo.udf_BitS_ToInt ('00000000000000000000000000011010') as [26]
     , dbo.udf_BitS_ToInt ('11010') as [26 sans leading 0s]
     , fn_replbitstringtoint ('11010') as [fn_replbit...]  
go
\-------Stop copying above this line ---------------------------/
(Results)
-1     Most positive num   26    26 sans leading 0s fn_replbit... 
------ ------------------- ----- ------------------ ------------- 
    -1          2147483647    26                 26    -805306368 

Using udf_BitS_FromInt and udf_BitS_ToInt together make it pretty
easy to use and understand ints as bit fields.


+--------------------------------------------------------------+
Do you have a great UDF that you'd like to share?  Or maybe you
have a T-SQL problem that you think could be solved by a UDF
but you don't know how? Send them to:

UDF@NovickSoftware.com 

and they might be published in this newsletter.  I try and 
respond to every request that I get.  

Thanks,  
Andrew Novick


RSS as HTML

Personal Blog

 
New Tips:

Loading SQL Profiler trace (.trc) files with fn_trace_gettrace

Upcoming
Presentations:

Big Data:
Working with Terabytes
in SQL Server

July 9 '08


Full Schedule