PostgreSQL 的 hstore、arrays 数据类型

PostgreSQL

官网地址:https://www.postgresql.org/

pgSQL 12.0 官网教程:https://www.postgresql.org/docs/12/index.html (PDF 版:postgresql-12-A4.pdf

hstore 数据类型

hstore 官网教程:https://www.postgresql.org/docs/12/hstore.html

hstore 中文教程:http://www.postgres.cn/docs/12/hstore.htmlhttps://www.sjkjc.com/postgresql/hstore-type/

辅助资料:https://wiki.postgresql.org/wiki/File:Pg-as-nosql-pgday-fosdem-2013.pdf (附件:Pg-as-nosql-pgday-fosdem-2013.pdf

hstore 数据类型

Postgres hstore 是 PostgreSQL 数据库中的一种特殊数据类型,它允许我们以键值对的形式保存和操作任意数量的数据。

hstore 类型的数据可以在查询时更加方便地进行复杂的条件搜索和匹配。我们可以使用 hstore 数据类型来存储 JSON 数据、动态属性集、键值对配置等复杂数据结构。

PostgreSQL HSTORE 数据类型很适合存储无规则的字典值,比如电子产品的属性,服装的规格等。

hstore 数据格式

HSTORE 类型字段是存储 k-v 数据的集合,key 和 value 之间使用 => 进行映射。多个 k-v 对之间使用英文逗号分隔

|-----------------------------------------------|
| "key1=>value1"[, "key2=>value2", ...] |

这里:

  • "key1=>value1" 是一个键值对。 如果键和值中不包含空格,可以省略双引号。
  • 多个键值对之间使用逗号分隔。
  • 键和值都是文本值。

启用 hstore

PostgreSQL HSTORE 数据类型在 hstore 模块中实现。要使用 PostgreSQL HSTORE 类型,需要启用扩展:

|----------------------------------|
| CREATE EXTENSION hstore; |

hstore 数据类型操作示例

库表数据准备

创建示例库表

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| CREATE TABLE "users" ( "id" serial PRIMARY KEY, "username" varchar(255) NOT NULL, "config" hstore ); COMMENT ON COLUMN "users"."id" IS '主键'; COMMENT ON COLUMN "users"."username" IS '用户名称'; COMMENT ON COLUMN "users"."config" IS '用户属性配置'; |

创建数据

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| INSERT INTO users ( username, config ) VALUES ('tom','"language"=>"Chinese","weight"=>"45 kg","email"=>"tom@xx.com"'); INSERT INTO users ( username, config ) VALUES ('jack','"language"=>"English","weight"=>"56 kg","email"=>"jack123@xx.com"'); INSERT INTO users ( username, config ) VALUES ('rose','"language"=>"Chinese","weight"=>"66.6 kg","email"=>"rose567@xx.com"'); INSERT INTO users ( username, config ) VALUES ('tony','"language"=>"English","weight"=>"50.2 kg","job"=>"barber"'); INSERT INTO users ( username, config ) VALUES ('jenny','"language"=>"Chinese","job"=>"chef","hight"=>"187"'); |

得到如下基础数据:

|------------------------------|
| SELECT * FROM users; |

查询 hstore 列

|-----------------------------------|
| SELECT config FROM users; |

查询指定 key 的数值

|------------------------------------------------------------|
| SELECT config -> 'email' AS user_email FROM users; |

where 条件查询

|---------------------------------------------------------------------|
| SELECT * FROM users WHERE config -> 'language' = 'Chinese'; |

更新 k-v 对

方式1

|--------------------------------------------------------------------------------------------------------------------|
| UPDATE users set config = config || hstore('email', 'rose345@xx.com') WHERE username = 'rose' returning *; |

returning * 表示返回成功影响行数的所有列信息

方式2

|---------------------------------------------------------------------------------------------------|
| UPDATE users set config['email'] = 'rose3456@xx.com' WHERE username = 'rose' returning *; |

returning * 表示返回成功影响行数的所有列信息

插入 k-v 对

和更新语法一致

方式1

|---------------------------------------------------------------------------------------------|
| UPDATE users set config['address'] = 'beijing' WHERE username = 'rose' RETURNING *; |

returning * 表示返回成功影响行数的所有列信息

方式2

|------------------------------------------------------------------------------------------------------------------|
| UPDATE users SET config = config || hstore ( 'address', 'shanghai' ) WHERE username = 'tom' RETURNING *; |

returning * 表示返回成功影响行数的所有列信息

删除 k-v 对

|----------------------------------------------------------------------------------------------------|
| UPDATE users SET config = DELETE ( config, 'address' ) WHERE username = 'tom' RETURNING *; |

returning * 表示返回成功影响行数的所有列信息

查询 hstore 列含有指定 key

|-----------------------------------------------------------------------------------------------------|
| SELECT username, config->'job' as job, config FROM users WHERE config ? ['job', 'address']; |

查询 hstore 列包含在指定 key 集合中

|-----------------------------------------------------------------------------------------------------------------------------------------|
| SELECT username, config->'job' as job, config->'address' as address, config FROM users WHERE config ?| ARRAY['job', 'address']; |

?| ARRAY['job', 'address'] 表示查询记录的 hstore 字段中 key 是否包含在指定字符串数组中。

查询 hstore 列全量包含指定 key 集合

|-----------------------------------------------------------------------------------------------------------------------------------------------|
| SELECT username, config->'email' as email, config->'address' as address, config FROM users WHERE config ?& ARRAY['email', 'address']; |

?& ARRAY['job', 'address'] 表示查询记录的 hstore 字段中 key 必须被指定字符串数组中所有元素包含。

查询 hstore 列所有 key

方式1

|-------------------------------------------------------|
| SELECT username, akeys ( config ) FROM users; |

方式2

|-------------------------------------------------------|
| SELECT username, skeys ( config ) FROM users; |

查询 hstore 列所有 key 并去重

|-----------------------------------------------------------------|
| SELECT DISTINCT UNNEST ( akeys ( config ) ) FROM users; |

查询 hstore 列所有 value

方式1

|-------------------------------------------------------|
| SELECT username, avals ( config ) FROM users; |

方式2

|-------------------------------------------------------|
| SELECT username, svals ( config ) FROM users; |

查询 hstore 列所有 value 并去重

|-----------------------------------------------------------------|
| SELECT DISTINCT UNNEST ( avals ( config ) ) FROM users; |

合并 k-v 对

|-------------------------------------------------------------------------------------------------------------------------------|
| SELECT username, config ::hstore || '"email"=>"tom"' ::hstore as newconfig, config FROM users WHERE username = 'jack' |

注意:||从左到右进行合并,如果 key 相同则后者覆盖掉前者

|-------------------------------------------------------------------------------------------------------------------------------|
| SELECT username, '"email"=>"tom"' ::hstore || config ::hstore as newconfig, config FROM users WHERE username = 'jack' |

查询 hstore 列表包含指定 k-v 对

查询包含:"language"=>"English" 的记录

|------------------------------------------------------------------------------------------------------|
| SELECT username, config FROM users WHERE config ::hstore @> '"language"=>"English"' ::hstore |

过滤指定 key 集合

|-------------------------------------------------------------------------------------------------------------------------------|
| SELECT username, config ::hstore - ARRAY['hight','language'] as newconfig, config FROM users WHERE username = 'jenny' |

过滤指定 key

|--------------------------------------------------------------------------------------------------------------------|
| SELECT username, config ::hstore - 'hight' ::text as newconfig, config FROM users WHERE username = 'jenny' |

Arrays 数据类型

Arrays 官网教程:https://www.postgresql.org/docs/12/arrays.html

hstore 中文教程:http://www.postgres.cn/docs/12/arrays.htmlhttps://www.sjkjc.com/postgresql/array-type/

arrays 列增加新元素

方式1

|--------------------------------------------------------------------------------------------------------------|
| UPDATE user_hobbies SET hobbies = ARRAY_APPEND(hobbies, 'draw') WHERE username = 'rose' RETURNING *; |

方式2

等同于:array_cat(hobbies, ARRAY['cook'])

|---------------------------------------------------------------------------------------------------------|
| UPDATE user_hobbies SET hobbies = hobbies || ARRAY['cook'] WHERE username = 'rose' RETURNING *; |

查看 arrays 列

|-----------------------------------------------------|
| SELECT username, hobbies FROM user_hobbies; |

操作数组类型列

arrays 列中元素是否存在指定元素

|--------------------------------------------------------------------------------------|
| SELECT username, hobbies FROM user_hobbies WHERE 'football' = ANY (hobbies); |

arrays 列中元素是否存在于指定数组

使用 && 运算符来检查两个数组是否有交集,如果有交集,就表示数组中的任一元素存在于目标数组中。

|-------------------------------------------------------------------------------------------------|
| SELECT username, hobbies FROM user_hobbies WHERE array['football', 'dance'] && hobbies; |

arrays 列中元素均不存在于指定数组

|-----------------------------------------------------------------------------------------------------------|
| SELECT username, hobbies FROM user_hobbies WHERE not(array['basketball', 'football'] && hobbies); |

指定数组是否为 arrays 列的子集

|---------------------------------------------------------------------------------------------|
| SELECT username, hobbies FROM user_hobbies WHERE array['dance', 'cook'] <@ hobbies; |

arrays 列是否为指定数组的子集

|------------------------------------------------------------------------------------------------------|
| SELECT username, hobbies FROM user_hobbies WHERE array['basketball', 'football'] @> hobbies; |

arrays 列中移除指定元素

|-----------------------------------------------------------------------------------------------------------------|
| UPDATE user_hobbies SET hobbies = array_remove ( hobbies, 'cook' ) WHERE username = 'rose' RETURNING *; |

参考资料

https://www.sjkjc.com/postgresql/hstore-type/

https://geek-docs.com/postgresql/postgresql-questions/455_postgresql_postgres_hstore_gin_vs_gist_index_performance.html

http://www.freeoa.net/osuport/db/pg-type-hstore-jsonb_3367.html

https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-hstore/

https://www.dbvis.com/thetable/storing-unstructured-data-with-hstore-in-postgresql/

https://blog.csdn.net/neweastsun/article/details/92849375

相关推荐
ever_up9739 分钟前
LangChain基础知识概述1
人工智能·python·langchain
豆豆23 分钟前
AI 建站实战:AI 生成前端页面如何集成自有 CMS 系统
人工智能·cms·网站搭建·网站管理系统·ai建站·建站工具·中小企业建站
cjy00011126 分钟前
2026年9月零基础能听懂国内 FDE 讲师的课吗?
大数据·前端·人工智能·fde
百胜软件@百胜软件40 分钟前
百胜软件SenClaw胜券助手正式发布:AI让数据“开口说话”,随时赋能零售运营
大数据·人工智能·零售
程序员天天困41 分钟前
Claude Fable 5.1 到底怎么样?扒完官方跑分和第三方榜单,说几句实话
人工智能·claude
喜欢睡觉1 小时前
LangChain 输出解析器:从裸文本到结构化输出
人工智能
工业涂料百问1 小时前
【市场格局】系列(四)汽车、船舶、风电涂料赛道对比:1400亿工业涂料里,哪个细分最“肥“?
人工智能·汽车
桃西西呀1 小时前
红酒标签上的 87 分是怎么算出来的?我拿 1599 瓶真酒把线性回归和逻辑回归拆开讲
人工智能·机器学习·llm
帅哥的AI自修课1 小时前
你的AI开发还是单打独斗?MetaGPT焊死「多智能体协作」,从角色分工到代码生成一篇打通
人工智能
HZZD_HZZD1 小时前
商业综合体分户计量与能源计费:业态差异、公区分摊与转供电合规
大数据·人工智能·能源