受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: devel

F.20. isn #

isn模块为以下国际产品编号标准提供数据类型:EAN13、UPC、ISBN(图书)、ISMN(音乐)和 ISSN(连续出版物)。输入这些编号时,会依据一份硬编码的前缀列表进行校验;输出时,这份前缀列表也会用于给编号加上连字符。由于新的前缀会不时被分配,这份前缀列表可能已经过时。希望该模块未来版本能从一个或多个表中获取前缀列表,以便用户按需更新;但目前,这份列表只能通过修改源代码并重新编译来更新。或者,该模块未来版本也可能取消前缀校验和连字符支持。

该模块被认为是受信任的,也就是说,它可以由在当前数据库上具有CREATE权限的非超级用户安装。

F.20.1. 数据类型 #

Table F.10显示了isn模块提供的数据类型。

Table F.10. isn 数据类型

数据类型 描述
EAN13 欧洲商品编号,始终以 EAN13 显示格式显示
ISBN13 以新的 EAN13 显示格式显示的国际标准图书编号
ISMN13 以新的 EAN13 显示格式显示的国际标准音乐编号
ISSN13 以新的 EAN13 显示格式显示的国际标准连续出版物编号
ISBN 以旧的短显示格式显示的国际标准图书编号
ISMN 以旧的短显示格式显示的国际标准音乐编号
ISSN 以旧的短显示格式显示的国际标准连续出版物编号
UPC 通用产品代码

几点说明:

  1. ISBN13、ISMN13 和 ISSN13 编号都是 EAN13 编号。

  2. EAN13 编号并不总是 ISBN13、ISMN13 或 ISSN13(不过其中有些确实是)。

  3. 某些 ISBN13 编号可以显示为 ISBN。

  4. 某些 ISMN13 编号可以显示为 ISMN。

  5. 某些 ISSN13 编号可以显示为 ISSN。

  6. UPC 编号是 EAN13 编号的一个子集(它们基本上就是去掉首位 0 的 EAN13 编号)。

  7. 所有 UPC、ISBN、ISMN 和 ISSN 编号都可以表示为 EAN13 编号。

在内部,所有这些类型都使用同一种表示形式(一个 64 位整数),并且彼此可以互换。之所以提供多种类型,是为了控制显示格式,并对原本应表示某一特定类型编号的输入执行更严格的有效性检查。

只要可能,ISBNISMNISSN 类型都会显示编号的短版本(ISxN 10);对于不能用短版本表示的编号,则显示为 ISxN 13 格式。EAN13ISBN13ISMN13ISSN13 类型则始终显示 ISxN 的长版本(EAN13)。

F.20.2. 类型转换 #

isn模块提供以下几对类型转换:

  • ISBN13 <=> EAN13

  • ISMN13 <=> EAN13

  • ISSN13 <=> EAN13

  • ISBN <=> EAN13

  • ISMN <=> EAN13

  • ISSN <=> EAN13

  • UPC <=> EAN13

  • ISBN <=> ISBN13

  • ISMN <=> ISMN13

  • ISSN <=> ISSN13

当从EAN13转换到其他类型时,会在运行时检查该值是否落在另一类型的取值范围内;如果不在,就会抛出错误。其他类型转换都只是简单地重新标记,因此总会成功。

F.20.3. 函数和操作符 #

isn模块提供标准比较操作符,以及对所有这些数据类型的 B-树和哈希索引支持。此外,它还提供了一些专用函数,如Table F.11所示。在该表中,isn表示该模块提供的任意一种数据类型。

Table F.11. isn 函数

函数

描述

make_valid ( isn ) → isn

清除该值上的“校验位无效”标记。

is_valid ( isn ) → boolean

检查该值是否带有“校验位无效”标记。

isn_weak ( boolean ) → boolean

设置弱输入模式,并返回新的设置值。保留此函数是为了向后兼容。推荐通过isn.weak配置参数来设置弱模式。

isn_weak () → boolean

返回弱模式的当前状态。保留此函数是为了向后兼容。推荐通过isn.weak配置参数来检查弱模式。


F.20.4. 配置参数 #

isn.weak (boolean) #

isn.weak启用弱输入模式,使得即使 ISN 输入值的校验位有误也会被接受。默认值为false,此时会拒绝无效校验位。

为什么会需要使用弱模式呢?例如,手头可能有一大批 ISBN 编号,数量多到难免会有一些编号因为某些奇怪的原因而带有错误的校验位(也许这些编号是从印刷清单扫描得到的,而 OCR 把数字识别错了;也许这些编号是人工录入的……谁知道呢)。总之,可能想把这些混乱情况清理干净,但同时仍希望先把所有编号都装入数据库,并借助外部工具在数据库中定位无效编号,以便核对信息并更容易完成校验;例如,可能会想把表中所有无效编号都查询出来。

当在弱模式下向表中插入无效编号时,实际插入的是校验位已更正的编号,但显示时会在末尾附加一个感叹号(!),例如0-11-000322-5!。可以用is_valid函数检查这个无效标记,并用make_valid函数清除它。

即使未启用弱模式,也可以通过在编号末尾附加!字符来强制插入被标记为无效的编号。

另一个特殊功能是,在输入时可以用?代替校验位,系统会自动插入正确的校验位。

F.20.5. 示例 #

--Using the types directly:
SELECT isbn('978-0-393-04002-9');
SELECT isbn13('0901690546');
SELECT issn('1436-4522');

--Casting types:
-- note that you can only cast from ean13 to another type when the
-- number would be valid in the realm of the target type;
-- thus, the following will NOT work: select isbn(ean13('0220356483481'));
-- but these will:
SELECT upc(ean13('0220356483481'));
SELECT ean13(upc('220356483481'));

--Create a table with a single column to hold ISBN numbers:
CREATE TABLE test (id isbn);
INSERT INTO test VALUES('9780393040029');

--Automatically calculate check digits (observe the '?'):
INSERT INTO test VALUES('220500896?');
INSERT INTO test VALUES('978055215372?');

SELECT issn('3251231?');
SELECT ismn('979047213542?');

--Using the weak mode:
SET isn.weak TO true;
INSERT INTO test VALUES('978-0-11-000533-4');
INSERT INTO test VALUES('9780141219307');
INSERT INTO test VALUES('2-205-00876-X');
SET isn.weak TO false;

SELECT id FROM test WHERE NOT is_valid(id);
UPDATE test SET id = make_valid(id) WHERE id = '2-205-00876-X!';

SELECT * FROM test;

SELECT isbn13(id) FROM test;

F.20.6. 参考文献 #

实现该模块所需的信息收集自若干网站,包括:

用于进行连字符分隔的前缀还整理自:

在创建这些算法时已十分谨慎,并依据官方 ISBN、ISMN、ISSN 用户手册中建议的算法进行了细致核验。

F.20.7. 作者 #

Germán Méndez Bravo (Kronuz), 2004–2006

该模块受到了 Garrett A. Wollman 的isbn_issn代码的启发。

提交更正

如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。