0

In PostgreSQL, my column type is json , the data is json array like:

[{"attsId": "42a2ce04-52ab-4a3c-8dfb-98c3d14b307d", "planId": 46, "filePath": "fileOperate\\upload", "cfileName": "潜在客户名单 (1).xls", "ufileName": "42a2ce04-52ab-4a3c-8dfb-98c3d14b307d.xls"}, {"attsId": "1adb2f13-00b0-4780-ae76-7a068dc3289c", "planId": 46, "filePath": "fileOperate\\upload", "cfileName": "潜在客户名单.xls", "ufileName": "1adb2f13-00b0-4780-ae76-7a068dc3289c.xls"}, {"attsid": "452f6c62-28df-47c7-8c30-038339f7b223", "planid": 48.0, "filepath": "fileoperate\\upload", "cfilename": "技术市场印花税.xls", "ufilename": "452f6c62-28df-47c7-8c30-038339f7b223.xls"}]

i want update one of the array date like:

UPDATE plan_base set atts->1='{"planId":"71"}' where id= 46;

how to do it? help me please

1 Answer 1

1

Here are two helper functions, to achieve your goal (requires PostgreSQL 9.3+):

This one can be used like UPDATEs (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.

Sign up to request clarification or add additional context in comments.

4 Comments

I want to change the type 'json' to 'jsonb' how to do it,I tried and failed, can you help me
pozs!!!Can you provide such a function like this:my jsonb array data is [{"attsId": "42a2ce04-52ab-4a3c-8dfb-98c3d14b307d", "planId": 46, "filePath": "fileOperate\\upload", "cfileName": "潜在客户名单 (1).xls", "ufileName": "42a2ce04-52ab-4a3c-8dfb-98c3d14b307d.xls"}],now i want loop the items and use key to update or find the item,can you help me Realization it,,,,
@MengQian from json to jsonb: within this function? Just change the types & casts. Or within a table's column? stackoverflow.com/questions/28202158/…
@MengQian you can expand your json array with json_array_elements() -- you can find many examples with it here (in SO) too (f.ex. my first function in this answer). If you have a specific problem, you can post it as a new question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.