バーコード(JANコード)のチェックディジットをSQLとPL/pgSQLで計算してみた

 バーコードを大量に生成する必要に迫られたので備忘録。

概要

 バーコードといっても複数の種類があり、主に日本国内で見かけるのはJANコードと呼ばれる13桁または7桁の番号です。

 そのどちらも、最後の1桁はチェックディジェットと呼ばれ、残りの1桁1桁からモジュラス10/ウェイト3といった方法で計算して求めます。

 今回、その「モジュラス10/ウェイト3」をSQLPL/pgSQLで再現しました。

 

SQL

select

    a.jan,

    case when a.ck = 10 then '0'::text else a.cd::text end as cd

from(

    select

        jan,

        10 - mod(

            case when length(jan) = 12 then 

              substr(jan, 12, 1)::integer * 3

                + substr(jan, 11, 1)::integer * 1

                + substr(jan, 10, 1)::integer * 3

                + substr(jan,  9, 1)::integer * 1

                + substr(jan,  8, 1)::integer * 3

                + substr(jan,  7, 1)::integer * 1

                + substr(jan,  6, 1)::integer * 3

                + substr(jan,  5, 1)::integer * 1

                + substr(jan,  4, 1)::integer * 3

                + substr(jan,  3, 1)::integer * 1

                + substr(jan,  2, 1)::integer * 3

                + substr(jan,  1, 1)::integer * 1        

            when length(jan) = 7 then

                substr(jan,  7, 1)::integer * 3

                + substr(jan,  6, 1)::integer * 1

                + substr(jan,  5, 1)::integer * 3

                + substr(jan,  4, 1)::integer * 1

                + substr(jan,  3, 1)::integer * 3

                + substr(jan,  2, 1)::integer * 1

                + substr(jan,  1, 1)::integer * 3

            else null end

        , 10) as cd

    from jans) as a;

PL/pgSQL

create or replace function calc_cd (text) returns text as $$

 

declare

x integer := 0;

len_code integer = length($1);

begin

if len_code <> 12 and len_code <> 7 then

return null::text;

end if;

 

for i in 1..len_code loop

case when (len_code - (i - 1)) % 2 = 1 then

x := x + substr($1, i, 1)::integer * 3;

else

x := x + substr($1, i, 1)::integer * 1;

end case;

end loop;

 

x := 10 - x % 10;

 

case when x = 10 then

return '0'::text;

else

return x::text;

end case;

end

$$ language plpgsql

returns null on null input

parallel safe;

 

 SQLは恐ろしいほど力業だけども、PL/pgSQLはそれっぽく書けたかもしれない。

参考元

アヴネット株式会社 | チェックデジット