Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/launchbadge/sqlx/llms.txt

Use this file to discover all available pages before exploring further.

SQLx provides a small family of free functions and a builder type that cover the full range of query execution patterns: from simple one-shot statements that return raw rows, to typed struct mapping, to dynamically constructed bulk inserts. Every function in this family produces a type that accepts .bind() calls for parameterized input and terminates with an executor method such as .fetch_one() or .execute().
All query functions require a runtime feature (runtime-tokio, runtime-async-std, etc.) to be enabled. The query!() macro family is documented separately on the Query macros reference page.

sqlx::query

pub fn query<'a, DB>(sql: impl SqlSafeStr) -> Query<'a, DB, <DB as Database>::Arguments>
where
    DB: Database,
Creates a single SQL query as a prepared statement. The connection transparently prepares and caches the statement so subsequent executions on the same connection reuse the cached query plan. The query string may contain only a single DML statement (SELECT, INSERT, UPDATE, DELETE, and variants). Use sqlx::raw_sql for DDL or multi-statement batches. Bind parameters are database-specific:
  • Postgres / SQLite: $1, $2, $3, … (the same placeholder may be reused)
  • MySQL / MariaDB: ? (purely positional; repeat the bind call to use a value multiple times)
Returns: Query<'_, DB, DB::Arguments>
let row = sqlx::query("SELECT id, name FROM users WHERE id = $1")
    .bind(42_i64)
    .fetch_one(&pool)
    .await?;
Never interpolate user input directly into the SQL string — that is a SQL injection vulnerability. Always use .bind() to pass dynamic values.

.bind(value)

Appends a bind parameter to the query. The call order must match the placeholder order in the SQL string (for MySQL/MariaDB) or the placeholder number (for Postgres/SQLite).
pub fn bind<'t, T: Encode<'t, DB> + Type<DB>>(self, value: T) -> Self

.persistent(bool)

Controls whether the prepared statement is cached on the connection (default: true). Set to false when the query string varies across calls, for example inside QueryBuilder, to avoid filling the statement cache.
pub fn persistent(self, value: bool) -> Self

sqlx::query_with

pub fn query_with<'q, DB, A>(sql: impl SqlSafeStr, arguments: A) -> Query<'q, DB, A>
where
    DB: Database,
    A: IntoArguments<DB>,
Identical to query() but accepts a pre-built Arguments object instead of building one incrementally with .bind(). Useful when constructing arguments programmatically. Returns: Query<'_, DB, A>

sqlx::query_as

pub fn query_as<'q, DB, O>(sql: impl SqlSafeStr)
    -> QueryAs<'q, DB, O, <DB as Database>::Arguments>
where
    DB: Database,
    O: for<'r> FromRow<'r, DB::Row>,
Like query(), but each returned row is automatically decoded into type O via the [FromRow] trait. O may be a named struct with #[derive(sqlx::FromRow)], or a tuple of up to 16 elements (columns matched by position). Returns: QueryAs<'_, DB, O, DB::Arguments>
#[derive(sqlx::FromRow)]
struct User {
    id: i64,
    name: String,
}

let user: User = sqlx::query_as("SELECT id, name FROM users WHERE id = $1")
    .bind(42_i64)
    .fetch_one(&pool)
    .await?;

sqlx::query_as_with

pub fn query_as_with<'q, DB, O, A>(sql: impl SqlSafeStr, arguments: A)
    -> QueryAs<'q, DB, O, A>
where
    DB: Database,
    A: IntoArguments<DB>,
    O: for<'r> FromRow<'r, DB::Row>,
Combines query_as with pre-built arguments, analogous to query_with.

sqlx::query_scalar

pub fn query_scalar<'q, DB, O>(sql: impl SqlSafeStr)
    -> QueryScalar<'q, DB, O, <DB as Database>::Arguments>
where
    DB: Database,
    (O,): for<'r> FromRow<'r, DB::Row>,
Extracts only the first column of each row and decodes it as type O. Additional columns are silently ignored. This is the most convenient API for aggregate queries (COUNT, MAX, SUM, EXISTS) and single-column lookups. Returns: QueryScalar<'_, DB, O, DB::Arguments>
let count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM users WHERE active = true")
    .fetch_one(&pool)
    .await?;

sqlx::QueryBuilder

QueryBuilder constructs queries at runtime by concatenating SQL fragments and bind parameters. Use it when the shape of the query — the number of columns, filters, or VALUES rows — is not known at compile time.
pub struct QueryBuilder<DB: Database> { /* ... */ }

QueryBuilder::new(init)

pub fn new(init: impl Into<String>) -> Self
Starts a new builder with the given SQL prefix. The prefix is typically a static fragment like "INSERT INTO users(id, name) " or "SELECT * FROM t WHERE ".

.push(sql)

pub fn push(&mut self, sql: impl Display) -> &mut Self
Appends a raw SQL fragment. Only safe for static, trusted SQL. Never pass user-controlled input here.

.push_bind(value)

pub fn push_bind<'t, T: Encode<'t, DB> + Type<DB>>(&mut self, value: T) -> &mut Self
Appends a bind placeholder ($N or ?) and records the value. This is the safe path for dynamic input.

.push_values(tuples, builder_fn)

pub fn push_values<I, F>(&mut self, tuples: I, push_tuple: F) -> &mut Self
where
    I: IntoIterator,
    F: FnMut(Separated<'_, DB, &'static str>, I::Item),
Appends a VALUES (…), (…) clause from an iterator of tuples. The callback receives a Separated helper and the current item; call .push_bind() on the helper for each column value.

.separated(separator)

pub fn separated<Sep: Display>(&mut self, separator: Sep) -> Separated<'_, DB, Sep>
Returns a Separated helper that inserts separator before each subsequent push (but not before the first). Useful for IN (…) clauses and comma-separated lists.

.build()

pub fn build(&mut self) -> Query<'_, DB, <DB as Database>::Arguments>
Finalizes the builder and returns a Query ready for execution. The builder must be reset (via .reset()) before reuse.
let mut qb: QueryBuilder<Postgres> = QueryBuilder::new(
    "INSERT INTO users(id, name, email) "
);

qb.push_values(users.iter(), |mut b, user| {
    b.push_bind(user.id)
     .push_bind(&user.name)
     .push_bind(&user.email);
});

qb.build().execute(&pool).await?;
For Postgres, prefer arrays with UNNEST() for large bulk inserts — it avoids per-row bind-parameter overhead and can be significantly faster.

sqlx::raw_sql

pub fn raw_sql(sql: impl SqlSafeStr) -> RawSql<'_>
Creates an unprepared query suitable for DDL (CREATE TABLE, ALTER TABLE), multi-statement batches, and any SQL the database does not support as a prepared statement. Unlike query(), raw_sql does not prepare or cache the statement, and bind parameters are not supported. Use it for trusted, static SQL only. Returns: RawSql<'_>
sqlx::raw_sql(
    "CREATE TABLE IF NOT EXISTS events (
        id   BIGSERIAL PRIMARY KEY,
        name TEXT      NOT NULL
    )"
)
.execute(&pool)
.await?;

Query finalizers

All query types (Query, QueryAs, QueryScalar, Map, RawSql) expose the same set of terminal async methods. Call one of these to actually send the SQL to the database.
Runs the query and returns the database’s QueryResult (rows affected / last insert ID). Discards any rows returned.
pub async fn execute<E: Executor<'c, Database = DB>>(
    self,
    executor: E,
) -> Result<DB::QueryResult, Error>
let result = sqlx::query("DELETE FROM sessions WHERE expires_at < NOW()")
    .execute(&pool)
    .await?;
println!("deleted {} rows", result.rows_affected());
Executes and returns exactly the first row, or Error::RowNotFound if the result set is empty.
pub async fn fetch_one<E: Executor<'c, Database = DB>>(
    self,
    executor: E,
) -> Result<DB::Row, Error>
For best performance, write queries that naturally return at most one row (filtering by a unique key), or add LIMIT 1.
Executes and returns Some(row) for the first row, or None if the result set is empty.
pub async fn fetch_optional<E: Executor<'c, Database = DB>>(
    self,
    executor: E,
) -> Result<Option<DB::Row>, Error>
Executes and collects all rows into a Vec. Use with care — if the result set is unbounded this will exhaust available memory. Always pair with a LIMIT clause when possible.
pub async fn fetch_all<E: Executor<'c, Database = DB>>(
    self,
    executor: E,
) -> Result<Vec<DB::Row>, Error>
Returns a BoxStream that yields rows lazily. Use when you want to process rows one at a time without loading the entire result set into memory.
pub fn fetch<E: Executor<'c, Database = DB>>(
    self,
    executor: E,
) -> BoxStream<'_, Result<DB::Row, Error>>
use futures_util::TryStreamExt;

let mut rows = sqlx::query("SELECT id, name FROM users")
    .fetch(&pool);

while let Some(row) = rows.try_next().await? {
    println!("{}", row.get::<String, _>("name"));
}

Build docs developers (and LLMs) love