PostgreSQL 9.0和9.1之间枚举类型文字排序的差异

时间:2013-08-23 08:47:01

标签: sql postgresql postgresql-9.1 jooq postgresql-9.0

PostgreSQL 9.0和9.1之间enum类型的工作方式有一些奇怪的更新。 pg_catalog.pg_enum表在PostgreSQL 9.1中有一个新列enumsortorder。此顺序似乎会覆盖基于OID的先前枚举排序。

PostgreSQL 9.0 Documentation

  

特定枚举类型的OID保证按类型排序的方式排序,但不保证不相关枚举类型的OID排序。

PostgreSQL 9.1 Documentation

  

pg_enum行的OID遵循一条特殊规则:保证偶数OID的排序方式与其枚举类型的排序顺序相同。也就是说,如果两个偶数OID属于相同的枚举类型,则较小的OID必须具有较小的enumsortorder值。奇数编号的OID值与排序顺序无关。此规则允许枚举比较例程在许多常见情况下避免目录查找。创建和更改枚举类型的例程尝试尽可能将偶数OID分配给枚举值。

     

创建枚举类型时,会为其成员分配排序顺序位置1..n。但后来添加的成员可能会获得enumsortorder的负值或小数值。对这些值的唯一要求是它们在每个枚举类型中被正确排序和唯一。

我的问题

对于jOOQ code generator,我正在读取pg_catalog.pg_enum表,按OID排序枚举文字,就像它在PostgreSQL 9.0中指定的那样。使用udpated规范,似乎我enumsortorder对文字进行排序,这似乎行为不同,因为它尊重枚举文字插入“在中间”。

pg_catalog读取这些枚举文字的最可靠,跨版本兼容的方法是什么?

1 个答案:

答案 0 :(得分:2)

我认为你需要检查PostgreSQL版本并适当地改变行为,或者使用不接触目录的SQL来确定顺序。

对于后者的想法,给出虚拟枚举:

CREATE TYPE test_enum AS ENUM ('z','x','y');
ALTER TYPE test_enum ADD VALUE 'a' BEFORE 'x';

使用8.4及更新版本中提供的ORDER BY窗口函数,将枚举标签的强制转换为row_number枚举类型的值:

SELECT enumlabel, row_number() OVER (ORDER BY enumlabel::test_enum) AS sort_key
FROM pg_catalog.pg_enum
WHERE enumtypid = 'test_enum'::regtype;

这将为您提供按排序键排序的标签。在较旧的Pg版本中,Pg只会按枚举值的oid排序,在较新版本中它会使用enumsortorder,但你不必关心任何一种方式,你刚刚告诉PostgreSQL“对这些进行排序请进入正确的顺序“。

或者,如果您只是按服务器所需的顺序需要它们,请写:

SELECT enumlabel
FROM pg_catalog.pg_enum
WHERE enumtypid = 'test_enum'::regtype
ORDER BY enumlabel::test_enum