Update query
In this guide, you’ll see how to update data in a database using Studio, Console, or one of the drivers.
Understanding Update queries
An Update query is used to update data in a TypeDB database by matching existing data, deleting some of it,
and then inserting some other data instead.
A delete
and insert
clauses are executed once per every result
matched by the match
clause of the same Update query.
For a detailed explanation of the query see the Update query page.
Sending Update queries
Before you start, make sure you followed instructions from the Delete query page. The easiest way to send an Update query is to use Studio or Console:
-
Studio
-
Console
Follow the Studio manual to connect to TypeDB and select a project folder. Then use the steps below:
-
Use a drop-down list in the top toolbar to select a database.
-
Switch to
data
session andwrite
transaction types. -
Open a new tab and insert or type in an Update query, for example:
TypeQL Update querymatch $u isa user, has name 'Charlie', has email $e; delete $u has $e; insert $u has email 'charles@typedb.com';
-
Run the query by clicking the Run Query button.
-
Commit the changes by clicking the Commit query button.
-
Open a
data
session andwrite
transaction to the selected database (e.g.,sample_db
):transaction sample_db data write
-
Send the Update query:
match $u isa user, has name 'Charlie', has email $e; delete $u has $e; insert $u has email 'charles@typedb.com';
Push Enter twice to send the query.
-
Commit the changes:
commit
To send an Update query programmatically, use drivers:
-
Rust
-
Python
-
Node.js
-
Java
-
C#
-
C++
-
C
Follow the connection guide
to connect the driver
to a TypeDB server.
let databases = DatabaseManager::new(driver);
let db = databases.get(DB_NAME)?;
{
let session = Session::new(db, SessionType::Data)?;
{
let tx = session.transaction(TransactionType::Write)?;
let update_query = "
match
$u isa user, has name 'Charlie', has email $e;
delete
$u has $e;
insert
$u has email 'charles@typedb.com';
";
let response_count = tx.query().update(update_query)?.count();
if response_count == 1 {
tx.commit().resolve()?;
} else {
tx.force_close();
}
}
}
Follow the connection guide
to connect the driver
to a TypeDB server.
with driver.session(DB_NAME, SessionType.DATA) as session:
with session.transaction(TransactionType.WRITE) as tx:
update_query = """
match
$u isa user, has name "Charlie", has email $e;
delete
$u has $e;
insert
$u has email "charles@typedb.com";
"""
response = list(tx.query.update(update_query))
if len(response) == 1:
tx.commit()
else:
tx.close()
Follow the connection guide
to connect the driver
to a TypeDB server.
try {
session = await driver.session(DB_NAME, SessionType.DATA);
try {
tx = await session.transaction(TransactionType.WRITE);
const update_query = `
match
$u isa user, has name "Charlie", has email $e;
delete
$u has $e;
insert
$u has email "charles@typedb.com";
`;
let response = await tx.query.update(update_query).collect();
if (response.length == 1) {
await tx.commit();
}
else {await tx.close();}
}
finally {if (tx.isOpen()) {await tx.close()};}
}
finally {await session?.close();}
Follow the connection guide
to connect the driver
to a TypeDB server.
try (TypeDBSession session = driver.session(DB_NAME, TypeDBSession.Type.DATA)) {
try (TypeDBTransaction tx = session.transaction(TypeDBTransaction.Type.WRITE)) {
String updateQuery = """
match
$u isa user, has name "Charlie", has email $e;
delete
$u has $e;
insert
$u has email "charles@typedb.com";
""";
long response_count = tx.query().update(updateQuery).count();
if (response_count == 1) {
tx.commit();
} else {
tx.close();
}
}
}
Follow the connection guide
to connect the driver
to a TypeDB server.
using (ITypeDBSession session = driver.Session(DB_NAME, SessionType.Data)) {
using (ITypeDBTransaction tx = session.Transaction(TransactionType.Write)) {
string update_query = @"
match
$u isa user, has name 'Charlie', has email $e;
delete
$u has $e;
insert
$u has email 'charles@typedb.com';";
List<IConceptMap> response = tx.Query.Update(update_query).ToList();
if (response.Count == 1) {
tx.Commit();
} else {
tx.Close();
}
}
}
Follow the connection guide
to connect the driver
to a TypeDB server.
TypeDB::Options options;
TypeDB::Session session = driver.session(DB_NAME, TypeDB::SessionType::DATA, options);
{
TypeDB::Transaction tx = session.transaction(TypeDB::TransactionType::WRITE, options);
std::string updateQuery = R"(
match
$u isa user, has name "Charlie", has email $e;
delete
$u has $e;
insert
$u has email "charles@typedb.com";
)";
TypeDB::ConceptMapIterable result = tx.query.update(updateQuery);
int16_t i = 0;
for (TypeDB::ConceptMap& element : result) { i+=1; }
if (i == 1) {
tx.commit();
} else {
tx.close();
}
}
Follow the connection guide
to connect the driver
to a TypeDB server.
Options* opts = options_new();
session = session_new(databaseManager, DB_NAME, Data, opts);
tx = transaction_new(session, Write, opts);
if ((tx == NULL) || FAILED()) {
handle_error("Transaction failed to start.");
goto cleanup;
}
char query[512];
snprintf(query, sizeof(query), "match $u isa user, has name 'Charlie', has email $e; delete $u has $e; insert $u has email 'charles@typedb.com';");
ConceptMapIterator* insertResult = query_update(tx, query, opts);
if (FAILED()) {
handle_error("Query execution failed.");
goto cleanup;
}
ConceptMap* insertedCM = NULL;
int16_t counter = 0;
while ((insertedCM = concept_map_iterator_next(insertResult)) != NULL) {
counter++;
}
if ((counter == 1) || FAILED()) void_promise_resolve(transaction_commit(tx));
else {
handle_error("Transaction commit failed.");
goto cleanup;
}
session_close(session);
Response interpretation
An Update query returns all concepts that got inserted into the database.
Both delete
and insert
clauses are executed once per every result
matched by the match
clause of the same Update query.
The delete
clause of an Update query is executed the same number of times as the insert
clause,
but if a concept specified for deletion is no longer present in a database for any reason,
that would not produce an error.
The query will continue its execution.
You can check the response of an Update query to see what was inserted.
The response is a Stream/Iterator with a ConceptMap object for every execution of the insert
clause.
A ConceptMap object maps every variable from a query to a particular concept in a database.
Check the response
The easiest way to check the response for the query is to use a TypeDB client: Studio or Console. For more information on how to send the above Update query, see above the Sending Update queries section.
Both Studio and Console should produce similar results:
{
$e the-bob@typedb.com isa email;
$u iid 0x826e80018000000000000001 isa user;
$_0 the-bob@typedb.com isa email;
}
To process the response of an Update query programmatically, we need to collect the response and iterate through it. See the code to check the response for the number of inserts above, in the Sending Update queries section.
The example above checks the response of an Update query and commits the changes only if the number of
inserts is equal to the expected number (1
).
Otherwise, it closes the transaction without committing the changes.
Estimation with a read query
You can estimate the number of inserts in an Update query with a match
clause
by running a dedicated Fetch or Get query with the same match
clause in the same transaction.
Read queries can be used in a write
transaction, and write
transactions are snapshoted,
providing isolation from changes made by other transactions.
To estimate the number of inserts in an Update query,
use the same write
transaction to send any type of a read query with the same match
clause, as the Update query.
The most direct approach is to send an aggregated Get query to count the number of matches.
match
$u isa user, has name "Bob", has email $e;
get; count;
The response is a single number.
The aggregated number of matched results is equal to the number of times the delete
and insert
clauses
of a Delete query with the same match
clause in the same write
transaction will be executed.