Bun Sqlite

by secondsky88378361314fMIT227 starsListed Oct 8, 2026Updated Oct 8, 2026Repository updated 10 days ago

Use for bun:sqlite, SQLite operations, prepared statements, transactions, and queries.

AI-generated overview

Reference guide for using Bun's built-in bun:sqlite driver for SQLite queries, prepared statements and transactions.

What it does
This skill is an instructional reference for Bun's built-in SQLite driver, bun:sqlite. It shows how to open file-based, in-memory, read-only and strict databases, run queries, use prepared statements with positional or named parameters, and wrap writes in deferred, immediate or exclusive transactions. It also covers batch inserts, column type mapping, error handling with SQLiteError, database serialization and common performance pragmas.
When to use it
Use it when writing or reviewing Bun/TypeScript code that talks to SQLite through bun:sqlite. It is suited to questions about prepared statements, parameter binding, transactions, bulk inserts, error codes or pragma tuning.
Requirements
Requires the Bun runtime with its built-in bun:sqlite module; no extra packages or credentials are needed. It ships no scripts, only documentation, and mentions optional reference files that are not included.

Bun SQLite

Bun has a built-in, high-performance SQLite driver via bun:sqlite.

Quick Start

typescript
import { Database } from "bun:sqlite";
// Create/open databaseconst db = new Database("mydb.sqlite");
// Create tabledb.run(`  CREATE TABLE IF NOT EXISTS users (    id INTEGER PRIMARY KEY AUTOINCREMENT,    name TEXT NOT NULL,    email TEXT UNIQUE  )`);
// Insert datadb.run("INSERT INTO users (name, email) VALUES (?, ?)", ["Alice", "[email protected]"]);
// Query dataconst users = db.query("SELECT * FROM users").all();console.log(users);
// Closedb.close();

Opening Databases

typescript
import { Database } from "bun:sqlite";
// File-based databaseconst db = new Database("data.sqlite");
// In-memory databaseconst memDb = new Database(":memory:");
// Read-only modeconst readDb = new Database("data.sqlite", { readonly: true });
// Create if not exists (default)const createDb = new Database("new.sqlite", { create: true });
// Strict mode (recommended)const strictDb = new Database("strict.sqlite", { strict: true });

Running Queries

Direct Execution

typescript
// Run (for INSERT, UPDATE, DELETE, DDL)db.run("CREATE TABLE items (id INTEGER PRIMARY KEY, name TEXT)");db.run("INSERT INTO items (name) VALUES (?)", ["Item 1"]);db.run("DELETE FROM items WHERE id = ?", [1]);
// Get changes infoconst result = db.run("DELETE FROM items WHERE id > ?", [10]);console.log(result.changes); // Rows affectedconsole.log(result.lastInsertRowid); // Last inserted ID

Prepared Statements (Recommended)

typescript
// Create prepared statementconst stmt = db.prepare("SELECT * FROM users WHERE id = ?");
// Get single rowconst user = stmt.get(1);
// Get all rowsconst allUsers = db.prepare("SELECT * FROM users").all();
// Get values as arrayconst values = db.prepare("SELECT name, email FROM users").values();// [[name1, email1], [name2, email2], ...]
// Iterate with for...ofconst iter = db.prepare("SELECT * FROM users");for (const user of iter.iterate()) {  console.log(user);}

Parameters

Positional Parameters

typescript
const stmt = db.prepare("INSERT INTO users (name, email) VALUES (?, ?)");stmt.run("Bob", "[email protected]");
// Or as arraystmt.run(["Charlie", "[email protected]"]);

Named Parameters

typescript
const stmt = db.prepare("INSERT INTO users (name, email) VALUES ($name, $email)");stmt.run({ $name: "Dave", $email: "[email protected]" });
// Also works with : and @const stmt2 = db.prepare("SELECT * FROM users WHERE name = :name");stmt2.get({ name: "Dave" }); // Note: no colon in object key

Query Methods

typescript
const stmt = db.prepare("SELECT * FROM users WHERE active = ?");
// .get() - First row or nullconst first = stmt.get(true);
// .all() - All rows as arrayconst all = stmt.all(true);
// .values() - Rows as arrays (not objects)const values = stmt.values(true);// [[1, "Alice", true], [2, "Bob", true]]
// .iterate() - Iterator for memory efficiencyfor (const row of stmt.iterate(true)) {  processRow(row);}
// .run() - Execute without returning datadb.prepare("DELETE FROM cache WHERE expires < ?").run(Date.now());

Transactions

typescript
// Simple transactionconst insertMany = db.transaction((users: { name: string; email: string }[]) => {  const insert = db.prepare("INSERT INTO users (name, email) VALUES ($name, $email)");  for (const user of users) {    insert.run(user);  }  return users.length;});
const count = insertMany([  { name: "User1", email: "[email protected]" },  { name: "User2", email: "[email protected]" },]);
// Transaction modesconst tx = db.transaction(() => {  db.run('INSERT INTO users (name, email) VALUES (?, ?)', ['Alice', '[email protected]']);  db.run('UPDATE accounts SET balance = balance - 100 WHERE user_id = ?', [1]);});
tx.deferred();   // Default: defer lock until first writetx.immediate();  // Lock immediately on transaction starttx.exclusive();  // Exclusive lock, blocks all other connections

Batch Operations

typescript
// WAL mode for better concurrent performancedb.run("PRAGMA journal_mode = WAL");
// Bulk insert with transactionconst insertBulk = db.transaction((items: string[]) => {  const stmt = db.prepare("INSERT INTO items (name) VALUES (?)");  for (const item of items) {    stmt.run(item);  }});
insertBulk(["A", "B", "C", "D", "E"]);

Column Types

typescript
// SQLite types map to JavaScript/*  SQLite      JavaScript  ------      ----------  INTEGER     number | bigint  REAL        number  TEXT        string  BLOB        Uint8Array  NULL        null*/
// Handle BigInt for large integersconst bigStmt = db.prepare("SELECT COUNT(*) as count FROM users");const result = bigStmt.get();// result.count may be bigint if > Number.MAX_SAFE_INTEGER
// Store/retrieve Uint8Arraydb.run("INSERT INTO files (data) VALUES (?)", [new Uint8Array([1, 2, 3])]);const file = db.prepare("SELECT data FROM files WHERE id = ?").get(1);// file.data is Uint8Array

Column Definitions

typescript
// Get column infoconst stmt = db.prepare("SELECT * FROM users");const columns = stmt.columnNames;// ["id", "name", "email"]
// Type annotations (Bun extension)const typedStmt = db.prepare<{ id: number; name: string }, [number]>(  "SELECT id, name FROM users WHERE id = ?");const user = typedStmt.get(1);// user is typed as { id: number; name: string } | null

Error Handling

typescript
import { Database, SQLiteError } from "bun:sqlite";
try {  db.run("INSERT INTO users (email) VALUES (?)", ["[email protected]"]);} catch (error) {  if (error instanceof SQLiteError) {    console.error("SQLite error:", error.code, error.message);    // error.code: "SQLITE_CONSTRAINT_UNIQUE"  }  throw error;}

Database Management

typescript
// Close databasedb.close();
// Check if openconsole.log(db.inTransaction); // Is in transaction
// Serialize to bufferconst buffer = db.serialize();await Bun.write("backup.sqlite", buffer);
// Load from bufferconst data = await Bun.file("backup.sqlite").arrayBuffer();const restored = Database.deserialize(data);
// Filenameconsole.log(db.filename); // Path or ":memory:"

Common Patterns

Repository Pattern

typescript
import { Database } from "bun:sqlite";
interface User {  id: number;  name: string;  email: string;}
class UserRepository {  private db: Database;  private stmts: {    findById: ReturnType<Database["prepare"]>;    findAll: ReturnType<Database["prepare"]>;    create: ReturnType<Database["prepare"]>;    update: ReturnType<Database["prepare"]>;    delete: ReturnType<Database["prepare"]>;  };
  constructor(db: Database) {    this.db = db;    this.stmts = {      findById: db.prepare("SELECT * FROM users WHERE id = ?"),      findAll: db.prepare("SELECT * FROM users"),      create: db.prepare("INSERT INTO users (name, email) VALUES ($name, $email)"),      update: db.prepare("UPDATE users SET name = $name, email = $email WHERE id = $id"),      delete: db.prepare("DELETE FROM users WHERE id = ?"),    };  }
  findById(id: number): User | null {    return this.stmts.findById.get(id) as User | null;  }
  findAll(): User[] {    return this.stmts.findAll.all() as User[];  }
  create(user: Omit<User, "id">): number {    const result = this.stmts.create.run(user);    return Number(result.lastInsertRowid);  }}

Common Errors

ErrorCauseFix
SQLITE_CONSTRAINTConstraint violationCheck UNIQUE/FK constraints
SQLITE_BUSYDatabase lockedUse WAL mode, add retry logic
no such tableTable doesn't existRun CREATE TABLE first
database is lockedConcurrent accessEnable WAL mode

Performance Tips

sql
-- Enable WAL mode (better concurrency)PRAGMA journal_mode = WAL;
-- Faster writes (less durable)PRAGMA synchronous = NORMAL;
-- Increase cache sizePRAGMA cache_size = 10000;
-- Enable foreign keysPRAGMA foreign_keys = ON;

When to Load References

Load references/pragmas.md when:

  • Performance tuning
  • Journal modes
  • Memory configuration

Load references/fts.md when:

  • Full-text search
  • FTS5 configuration

Source and attribution

Source:secondsky/claude-skillsinplugins/bun/skills/bun-sqliteat commit8837836

License: MIT

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal