Skip to main content
This walkthrough takes you from an empty project to reading rows out of DuckDB using only better-duck-core. Every method here is part of the core driver API.
1

Add the dependency

This pulls in the default features (chrono, decimal). See Installation for why the exact version must be pinned.
2

Open a connection

The main handle is better_duck_core::connection::Connection. Open a private in-memory database, or a file (created if absent):
SQL methods take &mut self, so bind conn as mut.
Each Connection::open_in_memory() call creates its own isolated in-memory database — two such connections do not see each other’s tables. To share one database across connections, open a Database and connect() from it.
3

Run DDL and DML

Use execute_batch for one or more ;-separated statements (DuckDB does the splitting), and execute_with to bind positional parameters ($1, $2, …):
With the derive feature, the params! macro builds the &mut [&mut dyn AppendAble] slice for you: conn.execute_with("INSERT INTO events VALUES ($1, $2, $3)", &mut params![1_i32, "launch".to_owned(), 9.5_f64])?;
4

Query and read rows

execute prepares and runs one statement and returns a DuckResult, which is an Iterator<Item = Result<DuckRow>>. Read columns by name with get (case-sensitive) or by index with get_idx; each value is a DuckValue:
DuckValue is #[non_exhaustive] — always include a _ arm when you match on it, so your code keeps compiling as new variants are added.
5

(Optional) Materialize a result

A DuckResult holds a live FFI handle. To detach from it — for example to move the result out of a closure or across threads — call materialize() to get a ResultSet, which holds no FFI handles and is Send + Sync + Clone:

Full example

Where to go next

Connections & Database

Sharing a database, cloning connections, Config, interrupting queries.

Queries, Results & Values

Parameter binding, iterating results, DuckValue, and TableDescription.

Choosing an API

When to reach for the appender, UDFs, Diesel, or Tauri.

DuckDB essentials

Dialect, type mapping, extensions, and engine behavior.