# Executing queries

Run raw SurrealQL with bound parameters and decode results with the Kotlin SDK.

The [`.query()`](/docs/reference/kotlin/api/core/surreal-client.md#query) family runs raw [SurrealQL](/docs/reference/query-language.md) and is the foundation of the SDK - the [CRUD builders](/docs/reference/kotlin/concepts/data-manipulation.md) compile to SurrealQL and dispatch through it. Queries can be supplied as a string with a [`JsonObject`](/docs/reference/kotlin/concepts/value-types.md) of bound parameters, or built with the [`surql`](#building-queries) DSL.

## API references

<table>
	<thead>
		<tr>
			<th scope="col">Method</th>
			<th scope="col">Description</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td scope="row" data-label="Method"><a href="/docs/reference/kotlin/api/core/surreal-client.md#query"><code>client.query(sql, vars)</code></a></td>
			<td scope="row" data-label="Description">Runs SurrealQL and returns the raw result</td>
		</tr>
		<tr>
			<td scope="row" data-label="Method"><a href="/docs/reference/kotlin/api/core/surreal-client.md#query-as"><code>client.queryAs&lt;T&gt;(sql, vars)</code></a></td>
			<td scope="row" data-label="Description">Runs SurrealQL and decodes the result to <code>T</code></td>
		</tr>
		<tr>
			<td scope="row" data-label="Method"><a href="/docs/reference/kotlin/api/core/surreal-client.md#query"><code>client.queryResult(sql, vars)</code></a></td>
			<td scope="row" data-label="Description">Runs SurrealQL and returns a <code>Result</code></td>
		</tr>
		<tr>
			<td scope="row" data-label="Method"><a href="/docs/reference/kotlin/api/core/surreal-client.md#let"><code>client.let(key, value)</code></a></td>
			<td scope="row" data-label="Description">Defines a session parameter</td>
		</tr>
		<tr>
			<td scope="row" data-label="Method"><a href="/docs/reference/kotlin/api/core/surreal-client.md#unset"><code>client.unset(key)</code></a></td>
			<td scope="row" data-label="Description">Removes a session parameter</td>
		</tr>
	</tbody>
</table>

## Running a query

Pass SurrealQL and, optionally, a [`JsonObject`](/docs/reference/kotlin/concepts/value-types.md) of bound parameters. The result is returned as a [`JsonElement`](/docs/reference/kotlin/concepts/value-types.md).

```kotlin
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put

val result = client.query(
    "SELECT * FROM person WHERE age > \$min_age",
    buildJsonObject { put("min_age", 25) },
)
```

> [!NOTE]
> Always bind variables with the `vars` argument rather than interpolating values into the query string. This avoids SurrealQL injection and lets the server cache query plans.

## Decoding results

To decode a query result straight into your own types, use the inline [`.queryAs<T>()`](/docs/reference/kotlin/api/core/surreal-client.md#query-as) helper with a [`@Serializable`](/docs/reference/kotlin/concepts/serialization.md) type.

```kotlin
import kotlinx.serialization.Serializable

@Serializable
data class Person(val name: String, val age: Int)

val people: List<Person> = client.queryAs(
    "SELECT * FROM person WHERE age > \$min_age",
    buildJsonObject { put("min_age", 25) },
)
```

You can also decode an arbitrary [`JsonElement`](/docs/reference/kotlin/concepts/value-types.md) yourself with [`.decode<T>()`](/docs/reference/kotlin/api/core/surreal-client.md#decode).

## Result variants

Every networked call has a `...Result` companion that returns a [`Result`](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-result/) instead of throwing, which is useful when you prefer to handle failures functionally.

```kotlin
val outcome = client.queryResult("SELECT * FROM person")
outcome
    .onSuccess { println("got $it") }
    .onFailure { println("query failed: ${it.message}") }
```

See [Error handling](/docs/reference/kotlin/concepts/error-handling.md) for the exception hierarchy thrown by the non-`Result` variants.

## Session parameters

Define parameters that persist for the session with [`.let()`](/docs/reference/kotlin/api/core/surreal-client.md#let), and remove them with [`.unset()`](/docs/reference/kotlin/api/core/surreal-client.md#unset). These are referenced as `$name` in subsequent queries.

```kotlin
import kotlinx.serialization.json.JsonPrimitive

client.let("min_age", JsonPrimitive(18))
client.query("SELECT * FROM person WHERE age > \$min_age")
client.unset("min_age")
```

## Building queries

The [`surql`](/docs/reference/kotlin/api/core/query-builder.md#surql) DSL builds a parameterised `BoundQuery` with automatic binding of values and record identifiers.

```kotlin
import com.surrealdb.kotlin.query.surql

val bound = surql("SELECT * FROM person WHERE age > \$min", "min" to 25)
val result = client.query(bound)
```

## Learn more

- [SurrealClient API reference](/docs/reference/kotlin/api/core/surreal-client.md) for complete method signatures
- [Query builder reference](/docs/reference/kotlin/api/core/query-builder.md) for the fluent builders and `surql` DSL
- [Data manipulation](/docs/reference/kotlin/concepts/data-manipulation.md) for CRUD with the builders
- [Serialisation](/docs/reference/kotlin/concepts/serialization.md) for working with `@Serializable` types
