Tuesday
28Oct2008

Check Digit Routine using Mod 10

The following is a handy function that I wrote in SQL Server to return a check

digit for a string of numbers (in my case, a scanline). It uses the Luhn

Algorithm – also referred to as modulus 10. Starting with a string of

numbers, the algorithm works as follows:

 

178009067 (this is our number string)

 

Now, starting with the first digit on the RIGHT, take the sum of all digits,

doubling every other digit and adding them together. The first digit we should

double is the second from the right. We would get:

 

7 + (1 + 2) + 0 + (1 + 8) + 0 + 0 + 8 + (1 + 4) + 1 = 33

 

Our check digit will be whatever we need to add to this total to make it

divisible by 10. In this case our check digit is 7.

 

Here is a function that will automatically calculate a check digit when it is

passed a string of numbers.

 

set ANSI_NULLS ON

set QUOTED_IDENTIFIER ON

go

 

ALTER FUNCTION [dbo].[fnCalcCheckDigit] (@sOrig VARCHAR(34))

 

-- @sOrig represents the string you are sending to the function.

-- If you are calculating a check digit for an OCR scanline for

-- example, @sOrig should contain the full scanline. Make sure

-- your varchar is big enough to hold the string, but not

-- inefficiently large

 

RETURNS VARCHAR(1)

 

AS

BEGIN

 

DECLARE @i INT, @j INT, @total INT, @finish INT, @result BIT, @testMsg VARCHAR(50), @double BIT

 

-- @j will temporarily store the value of the string digit to be

-- added into the running total after each iteration

-- @finish will store the scanline and the check digit

-- @total will hold the running total and will be

-- incremented by @j

-- @double is a boolean variable that will represent if a

-- digit is odd or even (since every other digit must be

-- doubled and added to the running total.

 

SET @finish = 0

SET @total = 0

SET @sOrig =  LTRIM(@sOrig)

SET @sOrig =  RTRIM(@sOrig)

SET @i =      LEN(@sOrig)

 

-- Always start with an odd digit - our first digit to be

-- doubled will be the second from the right

 

SET @double = 0

 

WHILE @i > 0

 

BEGIN

       SELECT @j=(ASCII(SUBSTRING(@sOrig, @i, 1))-48)

             

              IF @double = 1

              BEGIN

                     SET @j = @j * 2

 

-- If the digit * 2 is a two digit number

-- (for example 8 * 2 = 16), then we need to add 1 + 6.

-- We can use 16 - 9, because any digit doubled minus

-- 9 will equal the sum of the two digits that make

-- up the number.

 

                     IF @j > 9

                     BEGIN

                           SET @j = @j - 9

                     END

                     SET @double = 0

              END

             

              ELSE

              BEGIN

-- Set this flag so we know to double the next digit

                     SET @double = 1

              END

             

              SET @total = @total + @j

              SET @i = @i - 1     

END

 

-- Take the modulus 10 - if it is equal to zero,

-- then check digit is zero, otherwise,

-- store the check digit in @finish

 

IF @total % 10 = 0

       SELECT @finish = 0

ELSE

       SELECT @finish = 10 - (@total % 10)

RETURN (@finish)

 

END