The UPDATE statement can be used to update existing records in the database. If the record does not exist, the statement will succeed but no records will be updated.
Note
This statement can not be used to create graph relationships. For that, use the RELATE or INSERT statement.
Note
UPDATE on a single record in SurrealDB 1.x will create the record if it does not exist. This behaviour is no longer the case in SurrealDB 2.0. To update and create a record if it does not exist in SurrealDB 2.0, use the UPSERT statement.
@target refers to either record output including an id field, or a record ID on its own.
Example usage
Let's look at some examples of how to use the UPDATE statement. First we'll create two person records with the CREATE statement so that the examples will produce a meaningful output.
-- Create a Schemaless person table with a random id CREATEpersonCONTENT{ name: 'John', company: 'Surrealist', skills: ['JavaScript', 'Go' , 'SurrealQL'] };
-- Create another person with a specific id CREATEperson:tobieCONTENT{ name: 'Tobie', company: 'SurrealDB', skills: ['JavaScript', 'Go' , 'SurrealQL'] };
Let's say we wanted to update the person table with a new field enjoys (an array), a new skill breathing to the existing skills field (another array), add a new numeric field called dollars, and a last_name field that relies on the existing name field to set its value.
To do this we would use the following query.
-- Update all records in a table -- The `enjoys` field will also be an array. -- The += operator alone is enough to infer the type UPDATEpersonSET dollars=50, skills+='breathing', enjoys+='reading', full_name=name+' Mc'+name+'erson';
For more specific updates, you can specify a record ID to update a single record. The following query will update the record with the ID person:tobie to add "Rust" as a skill.
-- Update a record with a specific string id to add a new skill: 'Rust' UPDATEperson:tobieSETskills+='Rust';
The UPDATE statement supports conditional matching of records using a WHERE clause. If the expression in the WHERE clause evaluates to true, then the respective record will be updated.
-- Update all records which match the condition that `company` is not equal to "SurrealDB" UPDATEpersonSETskills+="System design"WHEREcompany!="SurrealDB";
Instead of specifying record data using the SET clause, it is also possible to use the CONTENT keyword to specify the record data using a SurrealQL object.
-- Update all records with the same content UPDATEpersonCONTENT{ name: 'John', company: 'SurrealDB', skills: ['Rust', 'Go', 'JavaScript'], };
-- Oops, now they are both named John. -- Update a specific record with some content UPDATEperson:tobieCONTENT{ name: 'Tobie', company: 'SurrealDB', skills: ['Rust', 'Go', 'JavaScript'], };
Since version 2.1.0, a statement with a CONTENT clause will bypass READONLY fields instead of generating an error.
DEFINEFIELDcreatedONpersonTYPEdatetimeDEFAULTd'2024-01-01T00:00:00Z'READONLY; CREATEperson:gladysSETage=90; -- Does not try to modify `created` field, no error UPDATEperson:gladysCONTENT{age: 70};
Originally an alias for CONTENT, the REPLACE clause maintains the previous behaviour regarding READONLY fields. If the content following REPLACE does not match a record's READONLY fields, an error will be generated.
DEFINEFIELDcreatedONpersonTYPEdatetimeDEFAULTd'2024-01-01T00:00:00Z'READONLY; CREATEperson:gladysSETage=90; -- Attempts to change `created` field, error UPDATEperson:gladysREPLACE{age: 70}; -- `created` equals current value, query works UPDATEperson:gladysREPLACE{age: 70, created: d'2024-01-01T00:00:00Z'};
Instead of specifying the full record data using CONTENT or one field at a time using SET, it is also possible to merge-update only specific fields by using the MERGE keyword followed by on object containing the fields which are to be upserted.
-- Update certain fields on all records UPDATEpersonMERGE{ settings: { marketing: true, }, };
-- Update certain fields on a specific record UPDATEperson:tobieMERGE{ settings: { marketing: true, }, };
By default, the update statement returns the record value once the changes have been made. To change the return value of each record, use the RETURN clause, specifying NONE, BEFORE, AFTER, DIFF, a comma-separated list of specific fields or ad-hoc fields, or VALUE for a single field without its key name.
-- Don't return any result UPDATEpersonSETskills+='reading'RETURNNONE;
-- Return the changeset diff UPDATEpersonSETskills+='reading'RETURNDIFF;
-- Return the record before changes were applied UPDATEpersonSETskills+='reading'RETURNBEFORE;
-- Return the record after changes were applied (the default) UPDATEpersonSETskills+='reading'RETURNAFTER;
-- Return the value of the 'skills' field without the field name UPDATEpersonSETskills+='reading'RETURNVALUEskills;
-- Return a specific field only from the updated records UPDATEperson:tobieSETskills=['skiing', 'music']RETURNname, interests;
Using a timeout
When processing a large result set with many interconnected records, it is possible to use the TIMEOUT keyword to specify a timeout duration for the statement. If the statement continues beyond this duration, then the transaction will fail, no records will be updated in the database, and the statement will return an error.
As UPDATE before version 2.0.0 used to create a specified record ID if it did not exist, it was used in the .surql files generated by the surreal export command to export existing records in a database. As of version 2.0.0, the INSERT statement is used instead.
The EXPLAIN clause
When EXPLAIN is used:
The UPDATE statement returns an explanation, essentially revealing the execution plan to provide transparency and understanding of the query performance.
The records are not updated.
EXPLAIN can be followed by FULL to see the number of executed rows.