Question

Je l'ai mis en place le « MOD 10 » vérifier algorithme de chiffres à l'aide de SQL, pour le service postal des États-Unis Adresse Change Service Keyline selon la méthode dans leur document, mais il semble que je reçois les mauvais chiffres! Nos chaînes d'entrée ont des chiffres en eux, ce qui rend le calcul un peu plus facile. Quand je compare mes résultats avec les résultats de leur application de test, je reçois des numéros différents. Je ne comprends pas ce qui se passe? Quelqu'un voit-il quelque chose de mal avec mon algorithme? Il faut que ce soit quelque chose d'évident ...

La documentation de la méthode se trouve à la page 12-13 de ce document: http://www.usps.com/cpim/ftp/pubs/pub8a. pdf

peut être trouvé L'exemple d'application à: http://ribbs.usps.gov/acs/documents/tech_guides/KEYLINE. EXE

S'IL VOUS PLAÎT NOTE: Je fixe le code ci-dessous, en fonction de l'aide des utilisateurs du forum. Il en est ainsi que les futurs lecteurs pourront utiliser le code dans son intégralité.

ALTER function [dbo].[udf_create_acs] (@MasterCustomerId varchar(26))
returns varchar(30)
as
begin
    --this implements the "mod 10" check digit calculation
    --for the US Postal Service ACS function, from "Publication 8A"
    --found at "http://www.usps.com/cpim/ftp/pubs/pub8a.pdf"
    declare @result varchar(30)
    declare @current_char int
    declare @char_positions_odd varchar(10)
    declare @char_positions_even varchar(10)
    declare @total_value int
    declare @check_digit varchar(1)

    --These strings represent the pre-calculated values of each character
    --Example: '7' in an odd position in the input becomes 14, which is 1+4=5
    -- so the '7' is in position 5 in the string - zero-indexed
    set @char_positions_odd = '0516273849'
    set @char_positions_even = '0123456789'
    set @total_value = 0
    set @current_char = 1

    --stepping through the string one character at a time
    while (@current_char <= len(@MasterCustomerId)) begin
        --this is the calculation for the character's weighted value
        if (@current_char % 2 = 0) begin
            --it is an even position, so just add the digit's value
            set @total_value = @total_value + convert(int, substring(@MasterCustomerId, @current_char, 1))
        end else begin
            --it is an odd position, so add the pre-calculated value for the digit
            set @total_value = @total_value + (charindex(substring(@MasterCustomerId, @current_char, 1), @char_positions_odd) - 1)
        end

        set @current_char = @current_char + 1
    end

    --find the check digit (character) using the formula in the USPS document
    set @check_digit = convert(varchar,(10 - (@total_value % 10)) % 10)

    set @result = '#' + @MasterCustomerId + '   ' + @check_digit + '#'

    return @result
end
Était-ce utile?

La solution

set @check_digit = convert(varchar, (10 - (@total_value % 10)) % 10)

Autres conseils

Je ne sais pas pourquoi vous embêter avec l'ensemble des représentations de chaîne quand vous travaillez dans une langue ensembliste.

Je ferais probablement comme ci-dessous. J'ai couru quatre tests à travers et ils étaient tous avec succès. Vous pouvez étendre cette facilement pour gérer les caractères aussi bien et vous pourriez même faire la table permanente si vous voulez vraiment faire.

CREATE FUNCTION dbo.Get_Mod10
(
    @original_string    VARCHAR(26)
)
RETURNS VARCHAR(30)
AS
BEGIN
    DECLARE
        @value_mapping TABLE (original_char CHAR(1) NOT NULL, odd_value TINYINT NOT NULL, even_value TINYINT NOT NULL)

    INSERT INTO @value_mapping
    (
        original_char,
        odd_value,
        even_value
    )
    SELECT '0', 0, 0 UNION
    SELECT '1', 2, 1 UNION
    SELECT '2', 4, 2 UNION
    SELECT '3', 6, 3 UNION
    SELECT '4', 8, 4 UNION
    SELECT '5', 1, 5 UNION
    SELECT '6', 3, 6 UNION
    SELECT '7', 5, 7 UNION
    SELECT '8', 7, 8 UNION
    SELECT '9', 9, 9

    DECLARE
        @i              INT,
        @clean_string   VARCHAR(26),
        @len_string     TINYINT,
        @sum            SMALLINT

    SET @clean_string = REPLACE(@original_string, ' ', '')
    SET @len_string = LEN(@clean_string)
    SET @i = 1
    SET @sum = 0

    WHILE (@i <= @len_string)
    BEGIN
        SELECT
            @sum = @sum + CASE WHEN @i % 2 = 0 THEN even_value ELSE odd_value END
        FROM
            @value_mapping
        WHERE
            original_char = SUBSTRING(@clean_string, @i, 1)

        SET @i = @i + 1
    END

    RETURN (10 - (@sum % 10)) % 10
END
GO

Pourquoi est-ce que nous avons un mod supplémentaire:

convert (varchar, 10% << -

Le document indique que seul le dernier chiffre doit être soustrait de 10. Ai-je raté quelque chose?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top