如何在PostgreSQL中从SQL查询创建枚举?

时间:2013-05-12 18:29:45

标签: postgresql

我想从PostgreSQL中的列的不同值创建枚举。我想使用查询来创建类型的所有可能值,而不是从所有标签创建枚举。我期待的是:

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

但我不允许这样做。有没有办法实现这个目标?

4 个答案:

答案 0 :(得分:5)

如果流派类型是动态的,即您不时创建新的类型并重命名旧类型,或者如果您想保存每种类型类型的其他信息,@mu's advice@Marcello's implementation值得考虑 - 除了你应该使用text类型而不是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()正确转义字符串。
我将字符串聚合为string_agg()(PostgreSQL 9.0 +)。

答案 1 :(得分:2)

我认为你无法通过设计来实现

http://www.postgresql.org/docs/9.1/static/datatype-enum.html

  

枚举(枚举)类型是包含静态有序的数据类型   一组价值观。

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;

答案 2 :(得分: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

答案 3 :(得分: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$$;

fiddle