本には商品判別のためのバーコードがついています。
いわゆるISBNコード(JANコード)です。
ECショップでは本を取り扱うために本の書誌を記録するテーブルを作成しますが、その際にint型でいいだろう? ユニーク制約でいいか?とおもってはいけないません。
先に結論を書いてしまうと
- 文字が含まれる可能性がある
- 先頭に0が来る可能性がある
- ユニークではない
char型にして、ユニーク制約をつけないほうがよい理由
1. 文字「X」が含まれる可能性がある
ISBNコードには10桁と13桁があります。
10桁ISBNコードは9桁+チェックデジット1桁で構成されます。
古い体系ですが、一部で使うことがあり、チェックデジットに文字「X」がはいる可能性があります。
これはチェックデジットがモジュラス11、ウェイト10-2
という方法で算出されるためです。
計算方法をphpで書くと
/** * ISBN10桁のチェックディジットを返す */ function getCheckDigit10($jan9) { $sum = 0; $cnt = 0; for ($i = 10; ; $i--) { if ($cnt > 10) { break; } $sum += substr($jan9, $cnt, 1) * $i; $cnt++; } $remainder = $sum % 11; if ($remainder == 0) { return 0; } $check_digit = 11 - $remainder; if ($check_digit == 10) { $check_digit = 'X'; } return $check_digit; }
2. 先頭に0がつく可能性がある
ISBNコードと書きましたが、実際にバーコードになっているのはJANコードです。
そしてJANコードは先頭が「0」になる可能性があります。
本を売るショップとして取り扱いそうなJANコードは3種類。
- 一般商品JANコード
45,または49で始まる12桁+チェックデジット1桁の13桁JANコード。
45と49は日本に割り振られた国コードなので固定。
雑誌やグッズなどに使われています。 - 書籍JANコード
9784で始まる12桁+チェックデジット1桁の13桁JANコード。
978は世界共通の書籍コード
4は日本に割り振られた国コードなので固定。
いわゆる13桁ISBNコード。
コミックや書籍などに使われています。
バーコードは2段になっており、上段は書籍JANコード、分類・価格のコード。 - インストアコード
02、04、20〜29で始まる12桁+チェックデジット1桁の13桁JANコード。
ポイントカード、会員証やレジ袋などの管理・販売用に使われる、小売店が独自につくって使用してよいJANコード。
20〜29始まりのJANコードを使用すればいい話だが、02、04も準備しておくに越したことはない。
JANコードのチェックデジットはモジュラス10、ウエイト3-1
という方法で算出されるため0〜9の数字になります。
/** * ISBN13桁のチェックディジットを返す */ function getCheckDigit13($jan12) { $sum_odd = 0; $sum_even = 0; for ($i = 11; $i >= 0; $i--) { if ($i % 2) { $sum_odd += substr($jan12, $i, 1); } else { $sum_even += substr($jan12, $i, 1); } } $sum = $sum_odd * 3 + $sum_even; $division = $sum % 10; return (10 - $division) % 10; }
3. 同じJANコードが使われる
JANコードは同じコードが存在するのでユニークではありません。
- 書籍JANコードの場合
「今現在販売中の本」と限定すれば書籍JANコードはユニークになります。
ただし、本が絶版になったあと、そのJANコードは別の本に付番されます。
そのため、今までに発売したすべての本のJANコードだと同じJANコードをもつ本が複数存在します。 - 雑誌の一般商品JANコードの場合
雑誌に付番されている雑誌コードから一般商品JANコードが作成されます。
その際に西暦の下1桁を使用しているため、10年ごとに同じコードになります。
以上がISBNコード(JANコード)をint型、ユニーク制約にしては行けない理由でした。
10桁と13桁のどちらも記録できるようにしてあると便利かもしれません。