是否可以在Postgres中创建代数数据类型,然后将其用作列类型?
例如:
CREATE TYPE hoofed AS ENUM('horse', 'goat');
CREATE TYPE monkey AS ENUM('chimp','macaque');
CREATE TYPE ANIMAL AS ENUM(hoofed, monkey);
这失败了:
syntax error at or near "hoofed"
LINE 1: CREATE TYPE ANIMAL AS ENUM(hoofed, monkey);
可以做这样的事情吗?
最终我想做的是这样的事情:
CREATE TABLE zoo (
a ANIMAL,
name text
);
INSERT INTO zoo(a, name) VALUES('horse', 'bob');
INSERT INTO zoo(a, name) VALUES('macaque', 'jimmy');
以及两个记录都具有独立有效。
编辑: @abihabi87的响应下面 do 允许我实际上创建一种产品类型,但它仍然不允许我根据需要创建一个联合类型。
您无法从其他枚举类型中创建类型的枚举:
您可以创建喜欢:
的动物CREATE TYPE ANIMAL AS (h hoofed,m monkey);
使用的示例:
CREATE TABLE your_table
(
a ANIMAL
);
INSERT INTO your_table(a) select (select ('horse','macaque')::ANIMAL);
使用ENUM
类型,您无法实现动态类型组成/联合。但是,使用DOMAIN
类型,您可以实现类似的目标:
create function valid_any_domain(anyelement, variadic regtype[])
returns boolean
language plpgsql
immutable
as $func$
declare
t regtype;
begin
foreach t in array $2 loop
begin
execute format('select $1::%s', t) using $1;
exception
when not_null_violation or check_violation then
continue;
end;
return true;
end loop;
return false;
end;
$func$;
create domain hoofed as text
check (value in ('horse', 'goat'));
create domain monkey as text
check (value in ('chimp','macaque'));
create domain animal as text
check (valid_any_domain(value, 'hoofed', 'monkey'));
更改基本类型也将动态更改复合/联合类型,但仍需要手动约束验证(尤其是当从有效频谱中删除某些值时(:
alter domain hoofed drop constraint hoofed_check;
alter domain hoofed add check (value in ('horse', 'goat', 'zebra'));
alter domain animal validate constraint animal_check;
http://rextester.com/mbvc62095
Note :但是,使用DOMAIN
类型,您将丢失ENUM
属性:自定义订购。DOMAIN
S将始终使用基础类型的订购。
使用函数:
create or replace function create_enum(name, variadic regtype[])
returns void language plpgsql as $$
begin
execute format(
'create type %I as enum(%s)',
$1,
string_agg(quote_literal(enumlabel), ',' order by enumtypid, enumsortorder))
from pg_enum
where enumtypid = any($2);
end $$;
将新类型的名称和枚举类型的列表作为参数:
select create_enum('animal', 'hoofed', 'monkey');
select enum_range(null::animal) as animal;
animal
----------------------------
{horse,goat,chimp,macaque}
(1 row)
有效地尝试合并两种enum
类型。
有一些开放的问题:
- 可以有重复的字符串吗?
- 设计是 static (更改为
enum
类型hoofed
请勿更改type typeanimal
(或Dynamic(相反(。 - 完全合并两种
enum
类型或更多? - 由于元素的顺序很重要,因此
animal
中的元素顺序应该是多少? - 这是一次性操作还是打算重复使用?
假设
无重复,静态设计,两种enum
类型,现有的元素顺序和一次性操作。
您可以使用内置枚举支持功能enum_range(anyenum)
获取给定enum
类型的所有元素的数组。
DO
$$
BEGIN
EXECUTE (
SELECT 'CREATE TYPE animal AS ENUM ('
|| array_to_string(enum_range(null::hoofed)::text[]
|| enum_range(null::monkey)::text[], ''',''')
|| ''')'
);
END
$$;