4

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

PostgreSQL 9.0 文档

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

PostgreSQL 9.1 文档

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

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

我的问题

对于jOOQ 代码生成器,我正在阅读pg_catalog.pg_enum表格,按 OID 对枚举文字进行排序,这是在 PostgreSQL 9.0 中指定的方式。使用更新的规范,似乎我应该按 排序文字enumsortorder,这似乎表现不同,因为它尊重“中间”的枚举文字插入。

pg_catalog?

4

1 回答 1

5

我认为您需要检查 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
于 2013-08-23T09:09:10.297 回答