The Go SDK provides two ways to execute SurrealQL queries: Query for typed, parameterised queries and QueryRaw for composing multiple statements with per-statement results. Both are generic functions that work with *DB, *Session, and *Transaction.
This page covers running queries, parameterising them, handling multi-statement results, and managing connection-scoped variables.
API references
Function | Description |
|---|---|
surrealdb.Query[T](ctx, s, sql, vars) | Executes a SurrealQL query with typed results |
surrealdb.QueryRaw(ctx, s, queries) | Executes a batch of query statements with per-statement results |
db.Let(ctx, key, val) | Defines a variable on the connection for use in queries |
db.Unset(ctx, key) | Removes a previously defined connection variable |
Running a query
The Query function executes a SurrealQL string and returns typed results. The first type parameter specifies the expected result type. The second parameter s can be a *DB, *Session, or *Transaction.
results, err := surrealdb.Query[[]Person](ctx, db,
"SELECT * FROM persons WHERE age > $min_age",
map[string]any{"min_age": 18},
)
if err != nil {
log.Fatal(err)
}
for _, qr := range *results {
fmt.Println(qr.Status, qr.Result)
}The function returns *[]QueryResult[T], where each QueryResult contains the Status, execution Time, Result, and an optional Error for that statement.
Parameterising queries
Always use parameters ($name) instead of string interpolation to prevent injection attacks and ensure correct CBOR encoding of value types.
results, err := surrealdb.Query[[]Person](ctx, db,
"SELECT * FROM persons WHERE name = $name AND age > $age",
map[string]any{
"name": "Tobie",
"age": 25,
},
)Pass nil for the variables map when no parameters are needed:
results, err := surrealdb.Query[[]Person](ctx, db,
"SELECT * FROM persons",
nil,
)Handling multi-statement queries
When a query string contains multiple statements, Query returns a QueryResult for each statement. Check the Error field on each result to detect per-statement failures.
results, err := surrealdb.Query[[]any](ctx, db,
"CREATE person:tobie SET name = 'Tobie'; SELECT * FROM person;",
nil,
)
for i, qr := range *results {
if qr.Error != nil {
fmt.Printf("Statement %d failed: %s\n", i, qr.Error.Message)
continue
}
fmt.Printf("Statement %d: %v\n", i, qr.Result)
} The err returned by Query is a joined error containing all per-statement QueryError values. You can check individual statements via the Error field, or use errors.Is(err, &surrealdb.QueryError{}) on the returned error.
Composing queries with QueryRaw
QueryRaw lets you compose a batch of QueryStmt objects, each with its own SQL and variables. After execution, each statement's result is available via .GetResult().
stmts := []surrealdb.QueryStmt{
{SQL: "CREATE person:alice SET name = $name", Vars: map[string]any{"name": "Alice"}},
{SQL: "SELECT * FROM person", Vars: nil},
}
if err := surrealdb.QueryRaw(ctx, db, &stmts); err != nil {
log.Fatal(err)
}
var persons []Person
if err := stmts[1].GetResult(&persons); err != nil {
log.Fatal(err)
}Defining connection variables
Use .Let() to define a variable that persists on the connection and is available in all subsequent queries. Use .Unset() to remove it.
if err := db.Let(ctx, "app_version", "1.0.0"); err != nil {
log.Fatal(err)
}
results, err := surrealdb.Query[[]any](ctx, db,
"RETURN $app_version",
nil,
)
db.Unset(ctx, "app_version")Connection variables are scoped to the connection (or session if using sessions). They do not affect other connections. You can also build queries programmatically using the query builder.
Learn more
DB API reference for complete method signatures and parameters
Data manipulation for typed CRUD operations
Error handling for distinguishing between query errors and transport errors
Types reference for
QueryResultandQueryStmtdefinitionsSurrealQL statements for the query language syntax