Qualche tempo fa, in questo articolo, abbiamo analizzato l’algoritmo di calcolo della cifra di controllo di un codice UCC/EAN, chi si occupa di logistica conoscerà bene l’argomento.
Lo standard di codifica UCC/EAN richiede che ogni codice generato termini con una cifra compresa tra zero (0) e nove (9), chiamata cifra di controllo (dall’inglese check digit). Questa cifra è calcolata in funzione delle altre cifre che compongono il codice e ha lo scopo di garantire che il codice, stampato in formato barcode, sia interpretato correttamente dal lettore ottico.
La prima versione (1.0) della funzione che implementa, in T-SQL, l’algoritmo di calcolo della cifra di controllo di un codice UCC/EAN è disponibile qui:
http://www.ugiss.org/calcolo-della-cifra-di-controllo-di-un-codice-ean-ucc/
Guardando l’implementazione dell’algoritmo, però, si può notare che la soluzione adottata non è Set-Based, ma procedurale. Il codice UCC/EAN passato in input è trattato come un array sul quale vengono eseguiti cicli di calcolo utilizzando il classico WHILE, in accordo con l’algoritmo.
Come possiamo riscrivere la soluzione utilizzando un approccio Set-Based e non procedurale? Per prima cosa pensiamo di numerare virtualmente le cifre del codice da destra a sinistra (considerando che il tredicesimo carattere sia occupato da uno zero – si tratta del placeholder della cifra di controllo), usiamo quindi una delle Build-In function fornite by design da SQL Server, ovvero la funzione SUBSTRING (T-SQL), per accedere alle cifre in posizione pari e quelle in posizione dispari, consideriamo poi di addizionare le cifre in posizione pari moltiplicando il risultato per 3 e addizionandolo alla sommatoria delle cifre in posizione dispari. Il risultato deve essere sottratto dal multiplo di 10 superiore e il gioco è fatto!
Ecco la versione 2.0, Set-Based, della funzione che implementa l’algoritmo di calcolo della cifra di controllo di un codice UCC/EAN13:
CREATE OR ALTER FUNCTION dbo.UDF_GetCheckDigitUCCEAN13 (
@ACode AS VARCHAR(12)
)
RETURNS INTEGER
AS BEGIN
RETURN (10 - (3* CAST(SUBSTRING('0' + @ACode, 1, 1) AS INTEGER)
+ CAST(SUBSTRING('0' + @ACode, 2, 1) AS INTEGER)
+ 3* CAST(SUBSTRING('0' + @ACode, 3, 1) AS INTEGER)
+ CAST(SUBSTRING('0' + @ACode, 4, 1) AS INTEGER)
+ 3* CAST(SUBSTRING('0' + @ACode, 5, 1) AS INTEGER)
+ CAST(SUBSTRING('0' + @ACode, 6, 1) AS INTEGER)
+ 3* CAST(SUBSTRING('0' + @ACode, 7, 1) AS INTEGER)
+ CAST(SUBSTRING('0' + @ACode, 8, 1) AS INTEGER)
+ 3* CAST(SUBSTRING('0' + @ACode, 9, 1) AS INTEGER)
+ CAST(SUBSTRING('0' + @ACode, 10, 1) AS INTEGER)
+ 3* CAST(SUBSTRING('0' + @ACode, 11, 1) AS INTEGER)
+ CAST(SUBSTRING('0' + @ACode, 12, 1) AS INTEGER)
+ 3* CAST(SUBSTRING('0' + @ACode, 13, 1) AS INTEGER)
)%10
)%10 END; GO
Per analogia, è possibile implementare le rispettive funzioni di calcolo della cifra di controllo anche per i codici EAN12, EAN14 e per il codice SSCC.
Buon divertimento!
P.S. Grazie all’amico Pietro Gallerani per avermi segnalato un bug nella funzione dbo.UDF_GetCheckDigitUCCEAN13. La seconda divisione “%10” (aggiunta il 30/12/2018) è necessaria per calcolare correttamente la cifra di controllo anche quando il totale è 10 o multiplo di 10… in questo caso particolare la cifra di controllo corretta è zero (0) e non dieci (10).