枚举类型是包含一系列有序的静态值集合的一个数据类型,等于某些编程语言中的enum类型。
与MySQL不一样,在PostgreSQL中要使用枚举类型需要先使用CREATE TYPE来创建此枚举类型。示例如下。
先建一个名为“week”的枚举类型,并建一张测试表:
CREATE TYPE week AS ENUM ('Sun','Mon','Tues','Wed','Thur','Fri', 'Sat'); CREATE TABLE duty(person text, weekday week); INSERT INTO duty values('张三', 'Sun'); INSERT INTO duty values('李四', 'Mon'); INSERT INTO duty values('王二', 'Tues'); INSERT INTO duty values('赵五', 'Wed');
试着查询一条数据:
osdba=# SELECT * FROM duty WHERE weekday = 'Sun'; person | weekday --------+--------- 张三 | Sun (1 row)
如果输入的字符串不在枚举类型之间,则会报错:
osdba=# SELECT * FROM duty WHERE weekday = 'Sun.'; ERROR: invalid input value for enum week: "Sun." LINE 1: SELECT * FROM duty WHERE weekday = 'Sun.'; ^
在psql中可以使用“\dT”命令查看枚举类型的定义:
osdba=# \dT+ week List of data types Schema | Name | Internal name | Size | Elements | Access privileges | Description --------+------+---------------+------+----------+-------------------+------------- public | week | week | 4 | Sun +| | | | | | Mon +| | | | | | Tues +| | | | | | Wed +| | | | | | Thur +| | | | | | Fri +| | | | | | Sat | | (1 row)
直接查询表“pg_enum”也可以看到枚举类型的定义:
osdba=# select * from pg_enum; enumtypid | enumsortorder | enumlabel -----------+---------------+----------- 26394 | 1 | Sun 26394 | 2 | Mon 26394 | 3 | Tues 26394 | 4 | Wed 26394 | 5 | Thur 26394 | 6 | Fri 26394 | 7 | Sat (7 rows)
在枚举类型中,值的顺序是创建枚举类型时定义的顺序。所有的比较标准运算符及相关的聚集函数都可支持枚举类型。示例如下:
osdba=# SELECT min(weekday), max(weekday) FROM duty; min | max -----+----- Sun | Wed (1 row) osdba=# SELECT * FROM duty where weekday = (SELECT max(weekday) FROM duty); person | weekday --------+--------- 赵五 | Wed (1 row)
每个枚举类型都是独立的,不能与其他枚举类型混用。
一个枚举值在磁盘上占4字节空间。一个枚举值的文本标签长度由NAMEDATALEN设置并编译到PostgreSQL中,且是以标准编译的方式进行的,也就意味着,一个枚举值的文本标签长度至少是63字节。
枚举类型的值对大小写是敏感的,如“Mon”不等于“mon”。标签中的空格也是一样,如“Mon”(“Mon”后有一个空格)不等于“Mon”。
与枚举类型相关的函数见表5-21。
表5-21 枚举类型的函数
上面例子中的枚举类型“week”的定义如下:
CREATE TYPE week AS ENUM ('Sun','Mon','Tues','Wed','Thur','Fri', 'Sat');
除了两个参数形式的enum_range外,其余函数会忽略传递给它们的具体值,因为它们只关心声明的数据类型。使用null加上类型转换也会得到相同的结果,示例如下:
osdba=# select enum_first(null::week), enum_last(null::week); enum_first | enum_last ------------+----------- Sun | Sat (1 row)