我想从 PostgreSQL 中列的不同值创建一个枚举。我不想从所有标签创建枚举,而是想使用查询来创建它以获取该类型的所有可能值。我期待类似的东西:
CREATE TYPE genre_type AS ENUM
(select distinct genre from movies);
但我不允许这样做。有什么办法可以做到这一点?
我想从 PostgreSQL 中列的不同值创建一个枚举。我不想从所有标签创建枚举,而是想使用查询来创建它以获取该类型的所有可能值。我期待类似的东西:
CREATE TYPE genre_type AS ENUM
(select distinct genre from movies);
但我不允许这样做。有什么办法可以做到这一点?
如果流派类型在任何方面都是动态的,即您不时创建新的并重命名旧的,或者如果您想保存每种流派类型的附加信息,@mu 的建议和@Marcello 的实现将值得考虑 - 除了你应该只使用 typetext
而不是varchar(20)
并考虑ON UPDATE CASCADE
fk 约束。
除此之外,这是您要的食谱:
DO
$$
BEGIN
EXECUTE (
SELECT format('CREATE TYPE genre_type AS ENUM (%s)'
,string_agg(DISTINCT quote_literal(genre), ', '))
FROM movies);
END
$$
为此,您需要动态 SQL。简单的方法是一个DO
命令(PostgreSQL 9.0+)。
确保你的字符串用quote_literal()
. 我用(PostgreSQL 9.0+)
聚合字符串。string_agg()
我认为你不能通过设计来做到这一点。
http://www.postgresql.org/docs/9.1/static/datatype-enum.html
枚举(enum)类型是包含一组静态、有序值的数据类型。
SELECT 子句中的“DISTINCT”关键字让我认为您的架构没有完全规范化。
例如:
CREATE TABLE movies(
...
genre VARCHAR(20)
...
);
SELECT DISTINCT genre FROM movies;
应该变成:
CREATE TABLE genres(
id SERIAL PRIMARY KEY,
name VARCHAR(20)
);
CREATE TABLE movies (
id SERIAL PRIMARY KEY,
title VARCHAR(200),
genre INTEGER REFERENCES genres(id)
);
SELECT name FROM genres;
一种简单的方法是SELECT
在客户端中执行,然后从中复制名称。
我认为这就是你能做的一切。如果您查看文档http://www.postgresql.org/docs/9.3/static/sql-createtype.html,您会注意到有写CREATE TYPE name AS ENUM ( [ 'label' [, ... ] ] )
所以没有的就是关键字expression
。这意味着之后ENUM
可能没有表达式,而只有标签列表。
您可能需要遵循@muistooshort 的建议并创建一个流派表(您可以用 填充INSERT ... SELECT ...
),然后foreign key
为该表创建一个。
它可以在 pgsql 中完成。这是执行此操作的内联代码:
DO $$
DECLARE temp text;
BEGIN
SELECT INTO temp string_agg(DISTINCT quote_literal(genre),',') FROM movies;
EXECUTE 'CREATE TYPE foo AS ENUM ('||temp||')';
END$$;