您可以使用该列的CHECK约束阵列和"is contained by"操作:
create table pancakes (
color varchar(10)[] not null,
check (color <@ ARRAY['red', 'green', 'blue']::varchar[])
);
然后像这样的事情发生:
=> insert into pancakes values (ARRAY['red']);
INSERT 0 1
=> insert into pancakes values (ARRAY['red','green','blue']);
INSERT 0 1
=> insert into pancakes values (ARRAY['red','green','blue','black']);
ERROR: new row for relation "pancakes" violates check constraint "pancakes_color_check"
=> select * from pancakes;
color
------------------
{red}
{red,green,blue}
(2 rows)
这将允许在列{red,red}
虽然;如果不允许{red,red}
是很重要的,那么你可以添加一个函数来检查数组中独特的色彩值,并调整CHECK约束:
create function has_unique_colors(varchar[]) returns boolean as $$
select (select count(distinct c) from unnest($1) as dt(c)) = array_length($1, 1);
$$ language sql;
create table pancakes (
color varchar(10)[] not null,
check (color <@ ARRAY['red', 'green', 'blue']::varchar[] and has_unique_colors(color))
);
另一种选择是,在列的简单标量值关联表一堆。但是,如果您有六个这样的列,这可能会很麻烦。你也可以使用Erwin的函数版本,如果你需要担心“套”中的NULL:
create function has_unique_colors(varchar[]) returns boolean as $$
select not exists(select c from unnest($1) dt(c) group by 1 having count(*) > 1);
$$ language sql;
很好的答案。初读时,它对我没有帮助;不是因为它允许红色,红色,而是因为它似乎用那些花括号存储数据。不过,我想我可以检索值并用逗号加入它们。这口井可能工作。我一直在研究,似乎没有任何其他解决方案。谢谢。 – punkish
oooohh ...我回我的评论。答案仍然很好,但对我来说根本不起作用。最主要的原因是,我实际上无法将MySQL中现有的100万行+行转换为Postgres,而实际上并未改变过程中的数据。 – punkish
@punkish:我添加了一个解决唯一性问题的方法。大括号是PostgreSQL显示数组的方式。如果你真的希望它们以单个字符串的形式出现在数据库中,有一个'array_to_string'函数。无论您使用的是什么接口,都可以理解这些数组并将它们转换为您的语言的数组。 –