Data manipulation

The Python SDK provides dedicated methods for common CRUD operations on records and tables. These methods offer a structured alternative to writing raw SurrealQL, with built-in parameter handling and type safety.

This page covers how to target tables and records, and how to select, create, insert, update, merge, patch, and delete data.

API References

MethodDescription
db.select(record)Selects all records from a table, or a specific record
db.create(record, data?)Creates a new record with an optional data payload
db.insert(table, data)Inserts one or multiple records into a table
db.insert_relation(table, data)Inserts one or multiple relation records
db.update(record, data?)Replaces the entire content of a record or all records in a table
db.upsert(record, data?)Creates a record if it does not exist, or replaces it entirely
db.merge(record, data?)Merges data into an existing record, preserving unmentioned fields
db.patch(record, data?)Applies JSON Patch operations to a record or all records in a table
db.delete(record)Deletes a specific record or all records from a table

Targeting tables and records

Most data manipulation methods accept a record parameter that determines the scope of the operation. You can pass a table name as a string to target all records in that table, or a RecordID to target a specific record.

from surrealdb import RecordID

db.select("users")

db.select(RecordID("users", "tobie"))

When a string is passed, the operation applies to the entire table. When a RecordID is passed, it applies to the single record identified by that ID. See the RecordID reference for more on constructing record identifiers.

Selecting records

The .select() method retrieves records from the database. Pass a table name to get all records, or a RecordID to get a single record.

		from surrealdb import Surreal, RecordID

with Surreal("ws://localhost:8000") as db:
db.use("surrealdb", "docs")
db.signin({"username": "root", "password": "root"})

all_users = db.select("users")

tobie = db.select(RecordID("users", "tobie"))

When selecting a table, the method returns a list. When selecting a specific record, it returns a single value or None if the record does not exist.

Creating records

The .create() method creates a new record. Pass a table name to generate a random ID, or a RecordID to specify the ID explicitly.

		from surrealdb import RecordID

user = db.create("users", {
"name": "Alice",
"email": "alice@example.com",
"age": 30,
})

specific = db.create(RecordID("users", "tobie"), {
"name": "Tobie",
"email": "tobie@surrealdb.com",
"age": 35,
})

The method returns the created record, including any server-generated fields such as the id.

Inserting records

The .insert() method inserts one or more records into a table. This is useful for bulk operations where you need to add multiple records at once.

		db.insert("users", {"name": "Alice", "age": 30})

db.insert("users", [
{"name": "Bob", "age": 25},
{"name": "Charlie", "age": 40},
])

The .insert_relation() method works the same way but is designed for creating graph edges between records. Each record must include in and out fields pointing to the connected records.

		from surrealdb import RecordID

db.insert_relation("likes", {
"in": RecordID("users", "tobie"),
"out": RecordID("posts", 123),
})

db.insert_relation("likes", [
{"in": RecordID("users", "tobie"), "out": RecordID("posts", 123)},
{"in": RecordID("users", "jaime"), "out": RecordID("posts", 456)},
])

Replacing records

The .update() method replaces the entire content of a record or all records in a table. Any fields not included in the new data are removed.

		from surrealdb import RecordID

db.update(RecordID("users", "tobie"), {
"name": "Tobie",
"email": "tobie@surrealdb.com",
"active": True,
})

db.update("users", {"active": False})

Upserting records

The .upsert() method creates a record if it does not already exist, or replaces it entirely if it does. This combines the behavior of .create() and .update() in a single operation.

		from surrealdb import RecordID

db.upsert(RecordID("users", "tobie"), {
"name": "Tobie",
"email": "tobie@surrealdb.com",
"active": True,
})

Merging data

The .merge() method deep-merges the provided data into the existing record, preserving any fields that are not mentioned in the merge payload. This is useful for partial updates.

		from surrealdb import RecordID

db.merge(RecordID("users", "tobie"), {
"settings": {"active": True},
})

db.merge("users", {
"updated_at": "2026-02-25T12:00:00Z",
})

In the example above, only the settings.active field is changed on the specific record. All other fields on the record remain untouched.

Applying patches

The .patch() method applies JSON Patch (RFC 6902) operations to a record or all records in a table. Each operation is a dictionary with op, path, and optionally value fields.

		from surrealdb import RecordID

db.patch(RecordID("users", "tobie"), [
{"op": "replace", "path": "/settings/active", "value": False},
{"op": "add", "path": "/tags", "value": ["developer", "admin"]},
{"op": "remove", "path": "/temp"},
])

Supported operations include add, remove, replace, move, copy, and test.

Deleting records

The .delete() method removes a specific record or all records from a table. The method returns the deleted record(s).

		from surrealdb import RecordID

deleted = db.delete(RecordID("users", "tobie"))

all_deleted = db.delete("users")

Learn more