先科普下概念:PgSQL9.4 新增 JSONB 數據類型, JSONB 同時屬於 JSON (JavaScript Object Notation) 數據類型,jsonb 和 json 的輸入數據幾乎完全通用,最大的差別體現在效率上,json 存儲的數據幾乎和輸入數據一樣,存儲的是未解析的數據,調用函數時使用效率較低; 而 jsonb 存儲的是分解的 binary 格式數據,使用時不需要再解析了,因此使用上效率較高; 另一方面 json 在寫入時較快,而 jsonb 寫入時由於需要轉換導致寫入較慢
目前網上的資料大量的介紹jsonb 的查詢操作,這里我不重復了
官方文檔介紹:http://www.postgresql.org/docs/9.4/static/datatype-json.html#JSON-CONTAINMENT
francs博客:http://francs3.blog.163.com/blog/static/40576727201452293027868/
json函數操作:http://www.postgresql.org/docs/9.5/static/functions-json.html
我一直在想問題,select 都可以了,那么update 的時候是像傳統的方式來操作嗎? 如果是,那么對於json這樣的數據更新就比較麻煩,
能不能這樣:
update api set jdoc->'guid'='ddddsxxx', jdoc->'name'='good' WHERE jdoc @> '{"company": "Magnafone"}'
經過我測試發覺pgsql會報語法錯誤,那么這樣肯定是不行了
看來只能這樣了:
這樣操作有一個弊端,那就是在更新的時候我就必須得知道content字段的全部內容,然后我才可以根據條件來更新,
那么實戰操作中 要知道content字段的全部內容 ,我又是不是要select出來,然后再 update,這樣 就兩個操作了。
除了這樣目前 對於 jsonb字段的更新確實沒有更智能的方式,
如果大家有更好的方式,歡迎留言
后面我在國外論壇上找到了一些思路,
Here are two helper functions, to achieve your goal (requires PostgreSQL 9.3+):
This one can be used like UPDATE
s (only updates an index, if it's already exists):
CREATE OR REPLACE FUNCTION "json_array_update_index"( "json" json, "index_to_update" INTEGER, "value_to_update" anyelement ) RETURNS json LANGUAGE sql IMMUTABLE STRICT AS $function$ SELECT concat('[', string_agg("element"::text, ','), ']')::json FROM (SELECT CASE row_number() OVER () - 1 WHEN "index_to_update" THEN to_json("value_to_update") ELSE "element" END "element" FROM json_array_elements("json") AS "element") AS "elements" $function$;
This one can be used, like an UPSERT
(updates an index, if it exists, or creates, if not -- using some default value to fill up unused indexes):
CREATE OR REPLACE FUNCTION "json_array_set_index"( "json" json, "index_to_set" INTEGER, "value_to_set" anyelement, "default_to_fill" json DEFAULT 'null' ) RETURNS json LANGUAGE sql IMMUTABLE STRICT AS $function$ SELECT concat('[', string_agg((CASE "index" WHEN "index_to_set" THEN to_json("value_to_set") ELSE COALESCE("json" -> "index", "default_to_fill") END)::text, ','), ']')::json FROM generate_series(0, GREATEST("index_to_set", json_array_length("json") - 1)) AS "index" $function$;
With these, you can UPDATE
any json data, like: 【外國人的最終解決方式為:】
UPDATE plan_base SET atts = json_array_update_index(atts, 1, '{"planId":"71"}'::json) WHERE id = 46;
Important! Json arrays are indexed from 0
(unlike other PostgreSQL arrays). My functions respect this kind of indexing.
SQLFiddle [意外收獲]
More about updating a JSON object:
Update: functions are now compacted.
我按照老外的這個思路把上面兩段創建函數的語句加到數據庫里面去
然后再把之前的更新語句做了一下調整
這些函數在我發本文的鏈連接里面有,這里不再重復
建好后,采用select 調用函數來能夠得到最終要更新的字符串如圖所示
最終更新還是得回到update上面
這里最后我們看到更新成功,數字變過來了。
這里通過寫函數來處理,把查詢構造都封裝好了。方便處理,在一次conection里面就能處理,比其之前我們select update 在程序里處理有了一定的進步
這里只是一種方式,如果諸位大神有更好的方式,歡迎留言