JSON

Update a field inside JSON

Short answer: modify a nested value without rewriting the whole document. Postgres uses jsonb_set(col, path, value). MySQL uses JSON_SET. Snowflake / BigQuery use OBJECT_INSERT / JSON_SET. SQL Server uses JSON_MODIFY. All take a JSON column, a path, and a new value, and return a new JSON document; pair with UPDATE to write it back.

Canonical SQL #

sql
-- Postgres: jsonb_set(target, path, new_value [, create_if_missing]).
UPDATE events
SET payload = JSONB_SET(payload, '{user,plan}', '"pro"'::JSONB)
WHERE id = 42;

-- Insert a key that doesn't exist yet (4th argument = TRUE, default).
UPDATE users
SET preferences = JSONB_SET(preferences, '{notifications,email}', 'true'::JSONB);

-- Remove a key.
UPDATE events SET payload = payload - 'temp_field' WHERE id = 42;
UPDATE events SET payload = payload #- '{user,profile,deprecated_field}' WHERE id = 42;

-- MySQL.
UPDATE events SET payload = JSON_SET(payload, '$.user.plan', 'pro') WHERE id = 42;
UPDATE events SET payload = JSON_REMOVE(payload, '$.temp_field') WHERE id = 42;

-- SQL Server.
UPDATE events SET payload = JSON_MODIFY(payload, '$.user.plan', 'pro') WHERE id = 42;

Example #

Loading SQL editor...

Common patterns #

sql
-- Increment a counter inside JSON.
UPDATE event_state
SET payload = JSONB_SET(
  payload,
  '{count}',
  TO_JSONB(((payload ->> 'count')::INT + 1))
)
WHERE id = 1;                                     -- Postgres

-- Merge two JSON objects (right side wins on key conflict).
UPDATE users
SET preferences = preferences || '{"theme":"slate","beta":true}'::JSONB
WHERE id = 42;                                     -- Postgres

-- Conditionally update only if the path exists.
UPDATE events
SET payload = JSONB_SET(payload, '{status}', '"verified"', FALSE)  -- 4th arg FALSE
WHERE payload ? 'status';                                            -- Postgres

-- Remove an item from a JSON array (replace with filtered array).
UPDATE users
SET tags = (SELECT JSONB_AGG(t) FROM JSONB_ARRAY_ELEMENTS(tags) AS t WHERE t::text <> '"old"')
WHERE id = 42;                                     -- Postgres

Dialect comparison #

EngineSyntaxGotcha
PostgreSQLjsonb_set(payload, '{user,plan}', '"pro"')path is an array literal, not $.user.plan; new value must be jsonb
MySQLJSON_SET(payload, '$.user.plan', 'pro')JSON_INSERT only adds; JSON_REPLACE only updates
SQL ServerJSON_MODIFY(payload, '$.user.plan', 'pro')new value NULL removes the key
BigQueryJSON_SET(payload, '$.user.plan', 'pro')native JSON type only; string-typed JSON must be rebuilt
SnowflakeOBJECT_INSERT(payload, 'plan', 'pro', TRUE)4th arg TRUE required to overwrite an existing key
OracleJSON_TRANSFORM(payload, SET '$.user.plan' = 'pro')21c+
SQLitejson_set(payload, '$.user.plan', 'pro')sets or inserts; json_replace updates only existing keys

Dialect notes #

  • Postgres: JSONB_SET(target, path, new_value, create_if_missing) is the workhorse. Path is an array literal ('{user,plan}'). || operator merges objects shallow; for deep merge, write a function. - removes a key; #- removes by path.
  • MySQL (5.7+): JSON_SET (set or insert), JSON_INSERT (only if missing), JSON_REPLACE (only if exists), JSON_REMOVE, JSON_MERGE_PATCH, JSON_MERGE_PRESERVE. JSONPath-style paths ('$.user.plan').
  • SQL Server (2016+): JSON_MODIFY(json, path, new_value) is one function for set/replace/remove. Pass NULL as new value to remove a key. Path uses $.field.
  • Snowflake: OBJECT_INSERT (add a field), OBJECT_DELETE (remove a field). Snowflake VARIANT columns are immutable, so every update returns a new document. OBJECT_INSERT(payload, 'plan', 'pro', TRUE) to update an existing key (4th arg = update_flag).
  • BigQuery: JSON_SET, JSON_REMOVE, JSON_STRIP_NULLS (newer JSON type). For string-typed JSON, manipulate as text or rebuild from JSON_VALUE extracts.
  • Oracle (21c+): JSON_TRANSFORM(json, SET '$.field' = ...), purpose-built for in-place edits.

FAQ #

How do I update a JSON field in PostgreSQL?

UPDATE events SET payload = jsonb_set(payload, '{user, plan}', '"pro"'::jsonb) WHERE id = 42. The path is an array literal of keys. Pass TRUE as the 4th argument (default) to create the path if missing; FALSE to update only when the path exists.

How do I update JSON in MySQL?

UPDATE events SET payload = JSON_SET(payload, '$.user.plan', 'pro') WHERE id = 42. JSONPath syntax ($.field). JSON_INSERT only adds if missing; JSON_REPLACE only updates if exists; JSON_SET does both. JSON_REMOVE deletes a key.

How do I update JSON in SQL Server?

UPDATE events SET payload = JSON_MODIFY(payload, '$.user.plan', 'pro') WHERE id = 42. Single function for set/replace/remove. Pass NULL as the new value to remove a key. Available since SQL Server 2016.

Does updating a JSON field rewrite the whole row?

Yes. The engine doesn't mutate the parsed JSON document in place; it stores a new copy. On a hot row, that turns the JSON column into a hot spot for vacuum / version churn. If a field changes often, promote it to its own column (where the engine can update just that column).

How do I remove a key from a JSON document?

Postgres: payload - 'field' (top-level) or payload #- '{user, profile, deprecated}' (path). MySQL: JSON_REMOVE(payload, '$.field'). Snowflake: OBJECT_DELETE(payload, 'field'). SQL Server: JSON_MODIFY(payload, '$.field', NULL).

How do I merge two JSON objects?

Postgres: payload || '{"new":1}'::jsonb (shallow merge, right wins on conflict). MySQL: JSON_MERGE_PATCH(a, b) (RFC 7396 merge semantics) or JSON_MERGE_PRESERVE (keeps duplicates). For deep merge with custom rules, write a function.

Warning

Updating JSON in place is rarely the right pattern at scale. Every update rewrites the entire row (the engine doesn't know how to mutate one byte of a parsed JSON document, so it stores a new copy). On a hot row, that turns the JSON column into a hot spot for vacuum / version churn. If a field changes often, promote it to its own column (where the engine can update just that column). JSON updates are right when most of the document changes together, or when changes are rare. Frequent surgical updates to a 500-key JSON blob is a modeling smell.