sql"…" — Template Seguro e Scalar
Nesta página
O literal sql"..." é uma forma mais expressiva de construir queries dinâmicas.
Qualquer {valor} dentro do template é compilado como ? e vinculado
automaticamente — você escreve a query como se fosse uma string interpolada, mas
com total segurança contra injeção.
O resultado é um TaggedSqlQuery com quatro métodos:
| Método | O que faz |
|---|---|
.query(db) |
Executa SELECT, retorna lista de maps |
.execute(db) |
Executa DDL/DML, retorna linhas afetadas |
.scalar(db) |
Retorna o primeiro valor da primeira linha |
.one(db) |
Retorna a primeira linha como map |
Filtra livros por ano com {min_year} e usa .scalar para contar o total.
// Feature: Database — `sql"..."` tagged template with auto-parametrization
// Syntax: `sql"SELECT ... WHERE x = {value}"` — interpolations become `?`
// and the values are bound. Returns a TaggedSqlQuery with methods
// `:query(db)`, `:execute(db)`, `:one(db)`, `:scalar(db)`.
// When to use: dynamic, safe queries without string concatenation.
use std::database::Database
let db = Database.open("sqlite://:memory:").unwrap()
defer db.close()
db.execute(sql"CREATE TABLE books (id INTEGER PRIMARY KEY, title TEXT, year INTEGER)").unwrap()
db.execute(sql"INSERT INTO books VALUES (1, 'Zolo Guide', 2025)").unwrap()
db.execute(sql"INSERT INTO books VALUES (2, 'Lua in 24h', 2010)").unwrap()
db.execute(sql"INSERT INTO books VALUES (3, 'Rust Book', 2020)").unwrap()
const min_year = 2020
// `{min_year}` compiles to `?` + binding — safe against injection.
let q = sql"SELECT title, year FROM books WHERE year >= {min_year} ORDER BY year"
let rows = q.query(db).unwrap()
for row in rows {
print(" {row.title} ({row.year})")
}
// expected:
// Rust Book (2020)
// Zolo Guide (2025)
// `:scalar` returns the first value of the first column.
let total = sql#"SELECT COUNT(*) "total" FROM books"#.scalar(db).unwrap()
print("total: {total}")
// expected: total: 3
Requer a CLI/host do Zolo — abra no playground ou rode localmente.
.scalar é o atalho ideal para agregações (COUNT, MAX, SUM) e
consultas que retornam exatamente uma célula:
Conta SKUs por valor com sql"...{target}".scalar(db) — o {target} é
vinculado, não concatenado.
// Feature: `sql"...".scalar(db)` — first column of first row, as a value
// Syntax: returns the value directly (number/string/bool/nil) rather
// than a row object.
// When to use: COUNT(*), MAX/MIN/SUM aggregates, SELECT 1, single
// scalar lookups by primary key — anywhere the result is exactly
// one cell.
use std::database::Database
let db = Database.open("sqlite://:memory:").unwrap()
defer db.close()
db.execute(sql"CREATE TABLE items (id INTEGER PRIMARY KEY, sku TEXT)").unwrap()
db.execute(sql"INSERT INTO items VALUES (1, 'a')").unwrap()
db.execute(sql"INSERT INTO items VALUES (2, 'b')").unwrap()
db.execute(sql"INSERT INTO items VALUES (3, 'a')").unwrap()
// Interpolated value is bound, not concatenated — safe.
let target = "a"
let n = sql"SELECT COUNT(*) FROM items WHERE sku = {target}".scalar(db).unwrap()
print("count: {n}")
// expected: count: 2
// `scalar` also works without interpolation.
let total = sql"SELECT COUNT(*) FROM items".scalar(db).unwrap()
print("total: {total}")
// expected: total: 3
Requer a CLI/host do Zolo — abra no playground ou rode localmente.
Desafio
Use sql"..." para calcular o preço médio com AVG(price) e exibir o resultado
formatado com duas casas decimais.
Veja também