如何更新Postgresql的Jsonb陣列

2021-10-04 23:29:00 字數 2750 閱讀 4682

假設你決定將資料以json或者jsonb的形式儲存在資料庫中,然後發現你剛剛給自己製造了新的問題,而這些問題是以前沒有的。

jsonb是乙個強大的工具,但它也有一定的代價,因為你需要調整查詢和處理資料的方式。

而且將整個jsonb物件載入到記憶體中,用你喜歡的程式語言進行轉換,然後將其儲存回資料庫,這並不罕見。但是,你剛剛創造了另乙個問題:效能瓶頸和資源浪費。

在這篇文章中,我們來看看如何通過一次查詢來更新陣列內物件的特定值。

假設你正在實現乙個為每個客戶儲存動態聯絡人功能,那麼你就會想到將聯絡人儲存為jsonb列,因為他們是動態的,因此使用非關係型資料結構是有意義的。

然後建立乙個帶有jsonb列聯絡人,並在其中插入一些資料。

create

table customers (name varchar

(256

), contacts jsonb)

;insert

into customers (name, contacts)

values

('jimi','[

,]');

insert

into customers (name, contacts)

values

('janis','[

]');

看起來很簡單,但是如何更新特定的聯絡人資訊?如何更改jimi的電子郵件或者janis的**?

幸運的是,postgresql提供了json_set函式。函式原型:

jsonb_set(target jsonb, path text, new_value jsonb[, create_missing boolean])
給定乙個jsonb列,可以在指定的路徑上設定乙個新值。

select jsonb_set(

'[,]',''

,'"[email protected]"'

,false);

select jsonb_set('',

'','"[email protected]"'

,false

);

jsonb_set函式的第乙個引數為jsonb資料物件,第二個引數路徑,在上面的例子中,為陣列中索引為1的元素,並且屬性是value欄位的,最後乙個引數是對路徑中選擇的字段進行賦值。

根據這樣的規則,那麼第乙個sql語句就是修改jimi的郵箱,而第二個sql語句就是修改janis的電子郵箱。

上面返回的結果是:

[,]
如果現在你認為這樣就完事了,那就是你太too young! too ******!

非關係型資料庫的問題在於它們是動態的,這也是使用jsonb的原因之一,但是這就帶來了乙個問題,例如上面的案例,jimi的郵箱物件在陣列中的索引是1,janis的郵箱物件在陣列中索引是0,而另外的一條資料很可能是不同的陣列,其索引也不一樣,那麼如何確定每個聯絡人的郵箱所在陣列的索引?

答案是對陣列中的元素進行排序,並獲得索引。

select

index-1

asindex

from customers

,jsonb_array_elements(contacts)

with ordinality arr(contact,

index

)where contact-

>>

'type'

='email'

and name =

'jimi'

;

該查詢會返回1,這是jimi聯絡人的電子郵件物件索引。

現在萬事俱備,只欠東風!我們把查詢和更改步驟合併。

with contact_email as

(select(''

)::text

as path

from customers

,jsonb_array_elements(contacts)

with ordinality arr(contact,

index

)where contact-

>>

'type'

='email'

and name =

'jimi'

)update customers

set contacts = jsonb_set(contacts, contact_email.path,

'"[email protected]"'

,false

)from contact_email

where name =

'jimi'

;

這個sql中最重要的部分就是with,這是乙個強大的命令,但對於這個例子來說,你可以把它看成是「儲存變數」功能,with最後的結果都儲存在contact_email變數內,其中就包含需要更新的路徑,也就是jimi的郵箱路徑。

下面再稍微詳細介紹一下:

(『』)::text as path
這一段是在建立路徑,但是要轉換成text型別,因為jsonb_set函式需要這個型別。

postgresql 實現插入 更新操作

insert into sip data sip ip 2m data time first,time last,ip,ip port,port values 2019 4 6 15 14 29 2019 4 6 14 59 28 203.190.77.198 203.190.77.198 4256...

PostgreSQL官方並行更新時間表

2013年10月,建立了兩個主要的基礎架構 dynamic background workers 和 dynamic shared memory。2014年11月,amit kapila發布了並行順序掃瞄 parallel sequential scan 的草案補丁,robert haas 發布了並...

PostgreSQL之時間戳自動更新

postgresql之時間戳自動更新 問題描述 postgresql執行insert語句時,自動填入時間的功能可以在建立表時實現,但更新表時時間戳不會自動自動更新。在mysql中可以在建立表時定義自動更新字段,比如 create table ab id int,age int,changetimes...