虽然不能像Catcall解释的那样将enum强制转换为整数,但可以使用特定于PostgreSQL且可能不兼容版本到版本的pg_enum
系统目录表来获取序号表示.
regress=# CREATE TYPE happiness AS ENUM ('happy', 'very happy', 'ecstatic');
regress=# select enumsortorder, enumlabel from pg_catalog.pg_enum
regress-# WHERE enumtypid = 'happiness'::regtype ORDER BY enumsortorder;
enumsortorder | enumlabel
---------------+------------
1 | happy
2 | very happy
3 | ecstatic
(3 rows)
这看起来很简单,但事实并非如此.注意:
regress=# ALTER TYPE happiness ADD VALUE 'sad' BEFORE 'happy';
regress=# ALTER TYPE happiness ADD VALUE 'miserable' BEFORE 'very happy';
regress=# SELECT * FROM pg_enum ;
enumtypid | enumsortorder | enumlabel
-----------+---------------+------------
185300 | 1 | happy
185300 | 2 | very happy
185300 | 3 | ecstatic
185300 | 0 | sad
185300 | 1.5 | miserable
(5 rows)
由此可以看出,enumsortorder
提供了订购,但没有固定的"距离".如果增加了对从枚举中删除值的支持,那么很可能也会在序列中创建"洞".
要获取枚举位置,需要使用row_number()
窗口函数来获取排序,使用pg_typeof
窗口函数来获取枚举类型的oid
(regtype
).当有多个具有相同标签的枚举时,需要使用此选项来确保返回正确的序号.
此功能完成以下任务:
CREATE OR REPLACE FUNCTION enum_to_position(anyenum) RETURNS integer AS $$
SELECT enumpos::integer FROM (
SELECT row_number() OVER (order by enumsortorder) AS enumpos,
enumsortorder,
enumlabel
FROM pg_catalog.pg_enum
WHERE enumtypid = pg_typeof($1)
) enum_ordering
WHERE enumlabel = ($1::text);
$$ LANGUAGE 'SQL' STABLE STRICT;
注:
STABLE
个索引,则会改变顺序);所以STRICT
,因为它应该为空输入返回空值现在,您可以使用此函数将特定枚举的值设置为CREATE CAST
到integer
.不能为integer
的所有枚举创建泛型转换,因为anyenum
伪类型不能用于转换.例如,如果我想将demo happiness
转换为整数,我会写:
CREATE CAST (happiness AS integer) WITH FUNCTION enum_to_position(anyenum);
之后我可以成功执行:
regress=# SELECT ('happy'::happiness)::integer;
int4
------
2
(1 row)
请注意,这可能是一个insane件事要做,是不受支持的,很可能是一个可怕的 idea .当您从枚举中添加或(如果以后支持)删除值时,代码必须知道序号值为will change.
如果更改枚举的定义(除了在末尾添加新值),基于此强制转换创建的索引(只有在函数定义为不可变的情况下才可能)将开始产生疯狂和错误的结果,因为当您说函数是不可变的时,PostgreSQL会相信您.不要那样做.