46 PostgreSql更新給定的數組的某一個元素

前言 

最近上有這樣一個問題, 項目上線之後, 上下一個版本的時候, 可能需要升級一部分的配置數據 之類的東西 

而 這部分的數據 有些可能是存放在 json數組 字段裏面的, postgresql 裏面是 json, jsonb 類型 

關於json, jsonb 的相關基礎介紹, 可以參見官方文檔 : http://www.postgres.cn/docs/10/datatype-json.html

然後 有這樣的需求, 就是 需要更新 json 數組裏面的某一個屬性爲 xx 的元素, 更新這個元素的其他屬性 

類似於有一個 List<User> friends, 需要更新 其中 name 爲 hx 的User 的 age 爲 43 

這種操作, 在網上搜索了一下 似乎相關的資料不是太多啊, 大多數文章介紹的就是 官方文檔上面的一些 簡單的示例, 沒辦法 只能自己來踩坑摸索了 

 

以下 sql 使用到的 postgresql 版本如下 

select version();

PostgreSQL 11.4 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609, 64-bit

 

 

參考代碼

相關表結構, 以及基礎數據準備如下 

## 測試建表語句 
CREATE TABLE "public"."user" (
"id" varchar(64) COLLATE "default" NOT NULL,
"code" varchar(32) COLLATE "default" DEFAULT ''::character varying,
"friends" jsonb,
CONSTRAINT "baseapp_bank_pkey" PRIMARY KEY ("id")
)
WITH (OIDS=FALSE)
;
ALTER TABLE "public"."user" OWNER TO "postgres";
COMMENT ON TABLE "public"."user" IS '用戶';
COMMENT ON COLUMN "public"."user"."code" IS '編碼';
COMMENT ON COLUMN "public"."user"."friends" IS '朋友列表';

# 添加測試數據 
delete from "public"."user";
INSERT INTO "public"."user" ("id", "code", "friends") VALUES ('1', 'dzt', '[{"age": "33", "code": "hx"}, {"age": "85", "code": "doit"}]');
INSERT INTO "public"."user" ("id", "code", "friends") VALUES ('2', 'hx', '[{"age": "36", "code": "dzt"}, {"age": "85", "code": "doit"}]');
INSERT INTO "public"."user" ("id", "code", "friends") VALUES ('3', 'doit', '[{"age": "36", "code": "dzt"}, {"age": "33", "code": "hx"}]');

初始化了三個用戶, 這三個用戶是彼此的朋友, 一個 dzt, 一個 hx, 一個 doit

 

現在我們想把 friends 這一列的裏面的 code 爲 hx 的元素, age 更新爲 43 

查詢更新結果

select u.id, u.code, 
jsonb_set(
friends,
concat(
   '{',
		(array_position(array(select jsonb_array_elements_text(friends) from "public"."user" where id = u.id),
			 (select jae::text from (
			select jsonb_array_elements(friends) as jae from "public"."user" where id = u.id
			) as tmp
			where jae::jsonb->>'code' = 'hx')
		) - 1),
	'}'
)::_text,
-- '{28}',
'{"age": "43", "code": "hx"}'::jsonb
)
from "public"."user" as u where 1 = 1
and (array_position(array(select jsonb_array_elements_text(friends) from "public"."user" where id = u.id),
			 (select jae::text from (
			select jsonb_array_elements(friends) as jae from "public"."user" where id = u.id
			) as tmp
			where jae::jsonb->>'code' = 'hx')
		) - 1) >= 0
;

 

執行結果如下 

得到了我們期望的結果, 我們期望 更新 dzt, doit 的 User 的 friends 列 並將其中的 code 爲 hx 的用戶 age 更新爲 43 

相信到這裏, 對應的 update 語句就更好寫了吧 

 

這裏面將 array_position 的結果 -1, 是因爲 數組下標是以 1 開始的 

 

 

這裏使用到的相關基礎知識整理如下 

---- common usage 
-- 1. 更新給定的路徑的 數據的值
select id, code, jsonb_set(friends, '{0, hobby}', '"game"', true) from "public"."user" where 1 = 1;
-- 2. 將json數組轉換爲 array 
select id, code, jsonb_array_elements(friends) from "public"."user" where code = 'dzt';
select id, code, array(select jsonb_array_elements(friends)) from "public"."user" where code = 'dzt';
-- 3. 查詢給定的 報表維度 的 name 爲給定的 key 的配置信息
select * from (
select id, code, jsonb_array_elements(friends) as jae from "public"."user" where 1 = 1
) as tmp
where jae::jsonb->>'code' = 'hx';

相關執行結果如下 

 

 

引用

postgresql數組操作符與函數
https://blog.csdn.net/pg_hgdb/article/details/79483767
關於pgsql 的json 和jsonb 的數據處理筆記
https://www.cnblogs.com/liuchuanfeng/p/8510270.html
postgreSQL查詢結果添加一個額外的自增序列
https://blog.csdn.net/camillect/article/details/85207934


postgresql 官方文檔相關
8.14. JSON 類型
http://www.postgres.cn/docs/10/datatype-json.html
8.15. 數組
http://www.postgres.cn/docs/10/arrays.html#ARRAYS-ACCESSING
9.15. JSON 函數和操作符
http://www.postgres.cn/docs/10/functions-json.html
9.18. 數組函數和操作符
http://www.postgres.cn/docs/10/functions-array.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章