docs/content/v2025.1/api/ycql/dml_update.md
Use the UPDATE statement to update one or more column values for a row in table.
{{< note title="Note" >}}
YugabyteDB can only update one row at a time. Updating multiple rows is currently not supported.
{{< /note >}}
<svg class="rrdiagram" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="930" height="220" viewbox="0 0 930 220"><path class="connector" d="M0 52h15m69 0h10m95 0h30m60 0h10m131 0h20m-236 0q5 0 5 5v8q0 5 5 5h211q5 0 5-5v-8q0-5 5-5m5 0h10m43 0h30m-5 0q-5 0-5-5v-20q0-5 5-5h39m24 0h40q5 0 5 5v20q0 5-5 5m-5 0h27m2 0h2m2 0h2m-651 50h2m2 0h2m2 0h7m66 0h10m137 0h30m32 0h30m104 0h238m-352 25q0 5 5 5h25m46 0h20m-81 0q5 0 5 5v8q0 5 5 5h56q5 0 5-5v-8q0-5 5-5m5 0h10m64 0h167q5 0 5-5m-347-25q5 0 5 5v65q0 5 5 5h5m104 0h10m38 0h30m46 0h20m-81 0q5 0 5 5v8q0 5 5 5h56q5 0 5-5v-8q0-5 5-5m5 0h10m64 0h5q5 0 5-5v-65q0-5 5-5m5 0h20m-439 0q5 0 5 5v98q0 5 5 5h414q5 0 5-5v-98q0-5 5-5m5 0h30m183 0h20m-218 0q5 0 5 5v8q0 5 5 5h193q5 0 5-5v-8q0-5 5-5m5 0h15"/><polygon points="0,59 5,52 0,45" style="fill:black;stroke-width:0"/><rect class="literal" x="15" y="35" width="69" height="25" rx="7"/><text class="text" x="25" y="52">UPDATE</text><a xlink:href="../grammar_diagrams#table-name"><rect class="rule" x="94" y="35" width="95" height="25"/><text class="text" x="104" y="52">table_name</text></a><rect class="literal" x="219" y="35" width="60" height="25" rx="7"/><text class="text" x="229" y="52">USING</text><a xlink:href="../grammar_diagrams#using-expression"><rect class="rule" x="289" y="35" width="131" height="25"/><text class="text" x="299" y="52">using_expression</text></a><rect class="literal" x="450" y="35" width="43" height="25" rx="7"/><text class="text" x="460" y="52">SET</text><rect class="literal" x="557" y="5" width="24" height="25" rx="7"/><text class="text" x="567" y="22">,</text><a xlink:href="../grammar_diagrams#assignment"><rect class="rule" x="523" y="35" width="93" height="25"/><text class="text" x="533" y="52">assignment</text></a><rect class="literal" x="15" y="85" width="66" height="25" rx="7"/><text class="text" x="25" y="102">WHERE</text><a xlink:href="../grammar_diagrams#where-expression"><rect class="rule" x="91" y="85" width="137" height="25"/><text class="text" x="101" y="102">where_expression</text></a><rect class="literal" x="258" y="85" width="32" height="25" rx="7"/><text class="text" x="268" y="102">IF</text><a xlink:href="../grammar_diagrams#if-expression"><rect class="rule" x="320" y="85" width="104" height="25"/><text class="text" x="330" y="102">if_expression</text></a><rect class="literal" x="340" y="115" width="46" height="25" rx="7"/><text class="text" x="350" y="132">NOT</text><rect class="literal" x="416" y="115" width="64" height="25" rx="7"/><text class="text" x="426" y="132">EXISTS</text><a xlink:href="../grammar_diagrams#if-expression"><rect class="rule" x="320" y="160" width="104" height="25"/><text class="text" x="330" y="177">if_expression</text></a><rect class="literal" x="434" y="160" width="38" height="25" rx="7"/><text class="text" x="444" y="177">OR</text><rect class="literal" x="502" y="160" width="46" height="25" rx="7"/><text class="text" x="512" y="177">NOT</text><rect class="literal" x="578" y="160" width="64" height="25" rx="7"/><text class="text" x="588" y="177">EXISTS</text><rect class="literal" x="712" y="85" width="183" height="25" rx="7"/><text class="text" x="722" y="102">RETURNS STATUS AS ROW</text><polygon points="926,109 930,109 930,95 926,95" style="fill:black;stroke-width:0"/></svg>
using_expression = ttl_or_timestamp_expression { 'AND' ttl_or_timestamp_expression };
<svg class="rrdiagram" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="246" height="65" viewbox="0 0 246 65"><path class="connector" d="M0 52h25m-5 0q-5 0-5-5v-20q0-5 5-5h80m46 0h80q5 0 5 5v20q0 5-5 5m-5 0h25"/><rect class="literal" x="100" y="5" width="46" height="25" rx="7"/><text class="text" x="110" y="22">AND</text><a xlink:href="../grammar_diagrams#ttl-or-timestamp-expression"><rect class="rule" x="25" y="35" width="196" height="25"/><text class="text" x="35" y="52">ttl_or_timestamp_expression</text></a></svg>
ttl_or_timestamp_expression = 'TTL' ttl_expression | 'TIMESTAMP' timestamp_expression;
<svg class="rrdiagram" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="305" height="65" viewbox="0 0 305 65"><path class="connector" d="M0 22h25m41 0h10m104 0h120m-290 0q5 0 5 5v20q0 5 5 5h5m90 0h10m155 0h5q5 0 5-5v-20q0-5 5-5m5 0h5"/><rect class="literal" x="25" y="5" width="41" height="25" rx="7"/><text class="text" x="35" y="22">TTL</text><a xlink:href="../grammar_diagrams#ttl-expression"><rect class="rule" x="76" y="5" width="104" height="25"/><text class="text" x="86" y="22">ttl_expression</text></a><rect class="literal" x="25" y="35" width="90" height="25" rx="7"/><text class="text" x="35" y="52">TIMESTAMP</text><a xlink:href="../grammar_diagrams#timestamp-expression"><rect class="rule" x="125" y="35" width="155" height="25"/><text class="text" x="135" y="52">timestamp_expression</text></a></svg>
update ::= UPDATE table_name [ USING using_expression ] SET assignment
[ , ... ] WHERE where_expression
[ IF { if_expression
| [ NOT ] EXISTS
| if_expression OR [ NOT ] EXISTS } ]
[ RETURNS STATUS AS ROW ]
assignment ::= { column_name | column_name'['index_expression']' } '=' expression
Where
table_name is an identifier (possibly qualified with a keyspace name).ttl_expression, where_expression, and if_expression are covered in the Semantics section.table_name does not exist.USING TIMESTAMP clause indicates you would like to perform the UPDATE as if it was done at the
timestamp provided by the user. The timestamp is the number of microseconds since epoch.USING TIMESTAMP clause in all of your statements or none of
them. Using a mix of statements where some have USING TIMESTAMP and others do not will lead to
very confusing results.USING TTL is not supported on tables with transactions enabled.UPDATE is always done at QUORUM consistency level irrespective of setting.WHERE clausewhere_expression and if_expression must evaluate to boolean values.where_expression must specify conditions for all primary-key columns.where_expression must not specify conditions for any regular columns.where_expression can only apply AND and = operators. Other operators are not yet supported.IF clauseif_expression can only apply to non-key columns (regular columns).if_expression can contain any logical and boolean operators.USING clausettl_expression must be an integer value (or a bind variable marker for prepared statements).timestamp_expression must be an integer value (or a bind variable marker for prepared statements).ycqlsh:example> CREATE TABLE employees(department_id INT,
employee_id INT,
name TEXT,
age INT,
PRIMARY KEY(department_id, employee_id));
ycqlsh:example> INSERT INTO employees(department_id, employee_id, name, age) VALUES (1, 1, 'John', 30);
Update the value of a non primary-key column.
ycqlsh:example> UPDATE employees SET name = 'Jack' WHERE department_id = 1 AND employee_id = 1;
Using upsert semantics to update a non-existent row (that is, insert the row).
ycqlsh:example> UPDATE employees SET name = 'Jane', age = 40 WHERE department_id = 1 AND employee_id = 2;
ycqlsh:example> SELECT * FROM employees;
department_id | employee_id | name | age
---------------+-------------+------+-----
1 | 1 | Jack | 30
1 | 2 | Jane | 40
IF clauseThe supported expressions are allowed in the 'SET' assignment targets.
ycqlsh:example> UPDATE employees SET age = age + 1 WHERE department_id = 1 AND employee_id = 1 IF name = 'Jack';
[applied]
-----------
True
Using upsert semantics to add a row, age is not set so will be 'null'.
ycqlsh:example> UPDATE employees SET name = 'Joe' WHERE department_id = 2 AND employee_id = 1 IF NOT EXISTS;
[applied]
-----------
True
ycqlsh:example> SELECT * FROM employees;
department_id | employee_id | name | age
---------------+-------------+------+------
2 | 1 | Joe | null
1 | 1 | Jack | 31
1 | 2 | Jane | 40
USING TTL clauseThe updated values will persist for the TTL duration.
ycqlsh:example> UPDATE employees USING TTL 10 SET age = 32 WHERE department_id = 1 AND employee_id = 1;
ycqlsh:example> SELECT * FROM employees WHERE department_id = 1 AND employee_id = 1;
department_id | employee_id | name | age
---------------+-------------+------+------
1 | 1 | Jack | 32
11 seconds after the update (value will have expired).
ycqlsh:example> SELECT * FROM employees WHERE department_id = 1 AND employee_id = 1;
department_id | employee_id | name | age
---------------+-------------+------+------
1 | 1 | Jack | null
USING TIMESTAMP clauseYou can do this as follows:
ycqlsh:foo> INSERT INTO employees(department_id, employee_id, name, age) VALUES (1, 4, 'Jeff', 20) USING TIMESTAMP 1000;
ycqlsh:foo> SELECT * FROM employees;
department_id | employee_id | name | age
---------------+-------------+------+------
1 | 1 | Jack | null
1 | 2 | Jane | 40
1 | 4 | Jeff | 20
2 | 1 | Joe | null
(4 rows)
Now update the employees table.
ycqlsh:foo> UPDATE employees USING TIMESTAMP 500 SET age = 30 WHERE department_id = 1 AND employee_id = 4;
Not applied since timestamp is lower than 1000.
ycqlsh:foo> SELECT * FROM employees;
department_id | employee_id | name | age
---------------+-------------+------+------
1 | 1 | Jack | null
1 | 2 | Jane | 40
1 | 4 | Jeff | 20
2 | 1 | Joe | null
(4 rows)
ycqlsh:foo> UPDATE employees USING TIMESTAMP 1500 SET age = 30 WHERE department_id = 1 AND employee_id = 4;
Applied since timestamp is higher than 1000.
ycqlsh:foo> SELECT * FROM employees;
department_id | employee_id | name | age
---------------+-------------+------+------
1 | 1 | Jack | null
1 | 2 | Jane | 40
1 | 4 | Jeff | 30
2 | 1 | Joe | null
(4 rows)
When executing a batch in YCQL, the protocol returns only one error or return status. The RETURNS STATUS AS ROW feature addresses this limitation and adds a status row for each statement.
See examples in batch docs.