【问题标题】:The difference in ordering of enum type literals between PostgreSQL 9.0 and 9.1PostgreSQL 9.0 和 9.1 之间枚举类型文字排序的差异
【发布时间】:2013-08-26 06:06:57
【问题描述】:

enum 类型在 PostgreSQL 9.0 和 9.1 之间的工作方式发生了一些奇怪的更新。 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 中指定的方式。使用更新的规范,我似乎应该enumsortorder 对文字进行排序,这似乎表现不同,因为它尊重“中间”的枚举文字插入。

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

【问题讨论】:

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


    【解决方案1】:

    我认为您需要检查 PostgreSQL 版本并适当更改行为,或者使用不涉及目录的 SQL 来确定排序。

    给定虚拟枚举,后者的想法:

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

    使用 8.4 及更高版本中可用的 row_number 窗口函数将枚举标签转换为枚举类型的值,以 ORDER BY

    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
    

    【讨论】:

    • 按标签排序是一种选择,但它可能不是 DDL 的作者想要的。我怀疑没有办法保持“在 DDL 中定义”的排序在 9.0 和 9.1 之间兼容?
    • @LukasEder 你没有注意到演员表。它不是按标签排序,而是通过将标​​签转换为枚举按枚举排序。编辑使其更加明显。
    • 太棒了! (虽然有点奇怪)。没错,我错过了演员阵容的重点。非常感谢
    • 对于未来的读者:值得补充的是,这种特殊的强制转换语法在 PostgreSQL 8.3 和其他 PostgreSQL 8.x 版本中不起作用。
    • @LukasEder 这不仅仅是语法;就是8.4之前的版本不支持窗口函数。由于 8.4 之前的版本也已过时且不受支持,因此我不会大惊小怪。尽管如此,还是调整了措辞。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-27
    • 2015-03-04
    • 2011-12-21
    • 1970-01-01
    • 2016-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多