我想从PostgreSQL中的列的不同值创建枚举。我想使用查询来创建类型的所有可能值,而不是从所有标签创建枚举。我期待的是:
CREATE TYPE genre_type AS ENUM
(select distinct genre from movies);
但我不允许这样做。有没有办法实现这个目标?
答案 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$$;