Data manipulation

The Go SDK provides generic top-level functions for common CRUD operations on records and tables. These functions work with *DB, *Session, and *Transaction through the sendable constraint, and return typed results through Go generics.

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

API References

FunctionDescription
surrealdb.Select[T](ctx, s, what)Selects all records from a table, or a specific record
surrealdb.Create[T](ctx, s, what, data)Creates a new record with optional data
surrealdb.Insert[T](ctx, s, table, data)Inserts one or multiple records into a table
surrealdb.InsertRelation[T](ctx, s, rel)Inserts a relation record between two records
surrealdb.Relate[T](ctx, s, rel)Creates a relation with an auto-generated ID
surrealdb.Update[T](ctx, s, what, data)Replaces the entire content of a record or all records in a table
surrealdb.Upsert[T](ctx, s, what, data)Creates a record if it does not exist, or replaces it entirely
surrealdb.Merge[T](ctx, s, what, data)Merges data into a record, preserving unmentioned fields
surrealdb.Patch(ctx, s, what, patches)Applies JSON Patch operations to a record or table
surrealdb.Delete[T](ctx, s, what)Deletes a specific record or all records from a table

Targeting tables and records

Most data manipulation functions accept a what parameter that determines the scope of the operation. You can pass a Table to target all records in a table, or a RecordID to target a specific record.

import "github.com/surrealdb/surrealdb.go/pkg/models"

all, err := surrealdb.Select[[]Person](ctx, db, models.Table("persons"))

one, err := surrealdb.Select[Person](ctx, db, models.NewRecordID("persons", "tobie"))

When a Table is passed, operations that return data return a slice. When a RecordID is passed, they return a single value. Use the appropriate type parameter to match.

Selecting records

Select retrieves records from the database. Pass a Table to get all records, or a RecordID to get a single record.

persons, err := surrealdb.Select[[]Person](ctx, db, models.Table("persons"))
if err != nil {
log.Fatal(err)
}

tobie, err := surrealdb.Select[Person](ctx, db, models.NewRecordID("persons", "tobie"))
if err != nil {
log.Fatal(err)
}

Creating records

Create creates a new record. Pass a Table to generate a random ID, or a RecordID to specify the ID explicitly. The data can be a struct or a map.

person, err := surrealdb.Create[Person](ctx, db, models.Table("persons"), Person{
Name: "Tobie",
Surname: "Morgan Hitchcock",
})

specific, err := surrealdb.Create[Person](ctx, db, models.NewRecordID("persons", "tobie"), map[string]any{
"name": "Tobie",
"surname": "Morgan Hitchcock",
})

Inserting records

Insert inserts one or more records into a table. This is useful for bulk operations.

persons, err := surrealdb.Insert[Person](ctx, db, models.Table("persons"), []map[string]any{
{"name": "Alice", "age": 30},
{"name": "Bob", "age": 25},
})

Creating relations

The SDK provides two ways to create graph edges between records.

Relate creates a relation with an auto-generated ID. The Relationship.ID field is ignored.

rel, err := surrealdb.Relate[map[string]any](ctx, db, &surrealdb.Relationship{
In: models.NewRecordID("persons", "tobie"),
Out: models.NewRecordID("posts", "first"),
Relation: models.Table("wrote"),
Data: map[string]any{"created_at": "2026-01-01T00:00:00Z"},
})

InsertRelation works like Insert but for relation tables. It allows you to specify the ID explicitly via the Relationship.ID field.

rel, err := surrealdb.InsertRelation[map[string]any](ctx, db, &surrealdb.Relationship{
In: models.NewRecordID("persons", "tobie"),
Out: models.NewRecordID("posts", "first"),
Relation: models.Table("wrote"),
})

Replacing records

Update replaces the entire content of a record or all records in a table. Fields not included in the new data are removed.

updated, err := surrealdb.Update[Person](ctx, db, models.NewRecordID("persons", "tobie"), Person{
Name: "Tobie",
Surname: "Morgan Hitchcock",
})

Upserting records

Upsert creates a record if it does not already exist, or replaces it entirely if it does.

person, err := surrealdb.Upsert[Person](ctx, db, models.NewRecordID("persons", "tobie"), Person{
Name: "Tobie",
Surname: "Morgan Hitchcock",
})

Merging data

Merge deep-merges the provided data into the existing record, preserving fields not mentioned in the merge payload.

merged, err := surrealdb.Merge[Person](ctx, db, models.NewRecordID("persons", "tobie"), map[string]any{
"age": 35,
})

Applying patches

Patch applies JSON Patch (RFC 6902) operations to a record or all records in a table. Each operation is a PatchData with Op, Path, and Value fields.

patches, err := surrealdb.Patch(ctx, db, models.NewRecordID("persons", "tobie"), []surrealdb.PatchData{
{Op: "replace", Path: "/surname", Value: "Hitchcock"},
{Op: "add", Path: "/verified", Value: true},
})

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

Deleting records

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

deleted, err := surrealdb.Delete[Person](ctx, db, models.NewRecordID("persons", "tobie"))

allDeleted, err := surrealdb.Delete[[]Person](ctx, db, models.Table("persons"))

Learn more