假設你決定將資料以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,
,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...