4

我想从 PostgreSQL 中列的不同值创建一个枚举。我不想从所有标签创建枚举,而是想使用查询来创建它以获取该类型的所有可能值。我期待类似的东西:

CREATE TYPE genre_type AS ENUM
   (select distinct genre from movies);

但我不允许这样做。有什么办法可以做到这一点?

4

4 回答 4

7

如果流派类型在任何方面都是动态的,即您不时创建新的并重命名旧的,或者如果您想保存每种流派类型的附加信息,@mu 的建议@Marcello 的实现将值得考虑 - 除了你应该只使用 typetext而不是varchar(20)并考虑ON UPDATE CASCADEfk 约束。

除此之外,这是您要的食谱

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()

于 2013-05-12T20:22:59.220 回答
2

我认为你不能通过设计来做到这一点。

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;
于 2013-05-12T19:27:19.497 回答
1

一种简单的方法是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为该表创建一个。

于 2013-05-12T19:13:58.820 回答
1

它可以在 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$$;

小提琴

于 2013-05-12T20:20:06.330 回答