Update or create nested jsonb value using single update command

后端 未结 2 1991
时光说笑
时光说笑 2021-02-05 17:56

Let us say I have [in Postgres 9.6] a JSONB column named xyz. In an update, I want to set the .foo.bar key of this column to {\"

2条回答
  •  萌比男神i
    2021-02-05 18:10

    For this example:

    { 
        "foo": {
            "baz": { "done": false }
        },
        "abc": "Hello"
    }
    

    INSERT:

    You have to use jsonb_insert you can test it with a SELECT.

    SELECT jsonb_insert(xyz, '{foo,bar}', '{"done":true}'::jsonb) FROM tablename;
    

    Note: With jsonb_insert is really important to set the path correctly. Here the path is '{foo:bar}' meaning that you will insert a JSON inside the object foo called bar.

    Hence, the result is:

    {
        "abc": "Hello",
        "foo": {
            "baz": {
                "done": false
            },
            "bar": {
                "done": true
            }
        }
    }
    

    SET:

    To edit bar and set it to false you have to use jsonb_set. You can test it with SELECT:

    SELECT jsonb_set(xyz, '{foo,bar}', '{"done":false}'::jsonb) FROM tablename;
    

    This returns:

    {
        "abc": "Hello",
        "foo": {
            "baz": {
                "done": false
            },
            "bar": {
                "done": false
            }
        }
    }
    

    UPDATE FOR SET AND INSERT

    You use jsonb_set when the object exists and jsonb_insert when it doesn't. To update without knowing which one to use, you can use CASE

    UPDATE tablename SET 
    xyz= (CASE
            WHEN xyz->'foo' IS NOT NULL
            THEN jsonb_set(xyz, '{foo,bar}', '{"done":false}'::jsonb)
            WHEN xyz->'foo' IS NULL
            THEN jsonb_insert(xyz, '{foo}', '{"bar":{"done":true}}'::jsonb)
        END)
    WHERE id=1;-- if you use an id to identify the JSON.
    

    You can add some CASE clauses for more specific values.

提交回复
热议问题