postgresql 什么postgres类型来存储一组字符串?

nr9pn0ug  于 2023-08-04  发布在  PostgreSQL
关注(0)|答案(3)|浏览(149)

在postgres中,我应该使用什么数据类型来存储一组唯一的字符串?
是用一个简单的数组然后当我想写的时候,我读取当前的字符串集合,确定最后的集合应该是什么,考虑唯一性然后写回来的最好方法?似乎有点效率低下。
我可能会经常做= ANY查询,以确定数组是否包含元素
一个可能的数据模型看起来像:

BlogPost
- title
- tags: string[]

字符串
2种常见操作:

  • 查找具有给定标签的博客文章
  • 更新标签列表(理想情况下保持它是一个唯一的集合)
thtygnil

thtygnil1#

我建议使用一个单独的表的标签。其优点是标签可以被索引并被有效地访问。索引进一步保证每个帖子的标签是唯一的。

create table blog_post (
  id int8 primary key,
  title varchar(255)
);

create table blog_tag (
  tag varchar(255),
  blog_post_id int8,
  constraint fk_blog_post foreign key(blog_post_id) references blog_post(id)
);

create unique index blog_tag_uk on blog_tag(tag, blog_post_id);

insert into blog_post values(1, 'title1');
insert into blog_tag values('tag-a', 1);
insert into blog_tag values('tag-b', 1);

insert into blog_post values(2, 'title2');
insert into blog_tag values('tag-a', 2);
insert into blog_tag values('tag-c', 2);

select *
from blog_post p left join blog_tag t on t.blog_post_id = p.id;

字符串

w7t8yxp5

w7t8yxp52#

我从你的问题中理解到,你想确保你为每个帖子都有一组唯一的字符串,如果是这样,那么你可以使用TEXT和UNIQUE来确保这样:

CREATE TABLE BlogPost (
  id SERIAL PRIMARY KEY,
  title TEXT,
  tags TEXT[] UNIQUE
);

字符串
UNIQUE将确保表中的每个集合都是唯一的。如果你尝试两次插入相同的集合,你会得到这样的错误:

postgres=# INSERT INTO BlogPost (tags) VALUES ('{"sql", "postgresql"}');
INSERT 0 1
postgres=# INSERT INTO BlogPost (tags) VALUES ('{"sql", "postgresql"}');
ERROR:  duplicate key value violates unique constraint "blogpost_tags_key"
DETAIL:  Key (tags)=({sql,postgresql}) already exists.


我希望这能回答你的问题,让我知道你的情况!

gcxthw6b

gcxthw6b3#

@ahmed_131313在正确的路径上,但其解决方案无法正确创建“唯一”数组。它确实禁止多次出现 exact same 数组。但是,is并不唯一地约束数组的元素;它允许{"postgresql", "sql"}{"sql", "postgresql"}。数组中的每个元素都存在于另一个数组中,并且没有一个元素不在另一个数组中。
您可以使用返回给定数组的有序唯一值的函数来创建唯一索引,而不是使用唯一约束。所以呢

create or replace function order_text_array(source_array_in text[])
  returns text[]
 language sql
 immutable 
 strict  
 parallel safe
/* 
 * order_text_array
 *   input text[]
 *  output text[]
 * 
 * Function returns ordered unique element values from a given array.
 * The functions discards duplicate value from the source as when viewed
 * as a SET the arrays '{"a", "x"}' and '{"a", "a", "x"}' are considered
 * the same set.
 * 
 * RULE: The sets A and B are the same if and only if
 *   For each element in either there exists the same element in the other 
 *   and there is no element in either set that is not in the other. 
 * 
 * Thus {A,B,C} and {A,B,B,C} are the same
 * and  {A,B,C} and {B,A,C} are also the same 
 */
as $$
    select array_agg(e) 
      from (select distinct(e) 
              from unnest(source_array_in) e
             order by 1
           ) sq  
$$;

字符串
然后定义没有唯一约束的表,但使用上述函数创建唯一索引。

create table blog_post (
                         id    integer generated always as identity 
                                       primary key
                       , title text
                       , tags text[] 
                       );
create unique index unique_single_blog_tag_list 
           on blog_post (order_text_array(tags));


请参见domo,其中显示了每个场景。

相关问题