# Batch Operations

> Run multiple SQL statements in one round-trip. Batch operations are atomic — if any statement fails, the entire batch rolls back.

Run multiple SQL statements in a single round-trip. Batch operations are transactional — if any statement fails, all are rolled back.

## Basic batch

```ts
const results = await sdk.db.batch([
  {
    sql: 'INSERT INTO orders (id, user_id, total) VALUES (?, ?, ?)',
    params: [orderId, userId, total]
  },
  {
    sql: 'UPDATE inventory SET stock = stock - ? WHERE product_id = ?',
    params: [quantity, productId]
  },
  {
    sql: 'INSERT INTO audit_log (action, entity_id, user_id, created_at) VALUES (?, ?, ?, ?)',
    params: ['order_created', orderId, userId, Date.now()]
  }
])
```

`results` is an array — one entry per statement, each with `{ results: T[] }`.

## Mixed read/write

```ts
const [newPost, _updated] = await sdk.db.batch([
  {
    sql: 'INSERT INTO posts (id, title) VALUES (?, ?) RETURNING *',
    params: [newId, title]
  },
  {
    sql: 'UPDATE users SET post_count = post_count + 1 WHERE id = ?',
    params: [userId]
  }
])

const post = newPost.results[0]
```

## Bulk insert

```ts
const items = [
  { id: '1', name: 'Item A', price: 10 },
  { id: '2', name: 'Item B', price: 20 },
  { id: '3', name: 'Item C', price: 30 },
]

await sdk.db.batch(
  items.map(item => ({
    sql: 'INSERT INTO products (id, name, price) VALUES (?, ?, ?)',
    params: [item.id, item.name, item.price]
  }))
)
```

The database (SQLite-compatible) does not support true parallel transactions. Batch statements run sequentially within a single transaction.

## Error handling

```ts
try {
  await sdk.db.batch([
    { sql: 'INSERT INTO orders ...', params: [...] },
    { sql: 'UPDATE inventory ...', params: [...] },
  ])
} catch (err) {
  // If any statement throws, the entire batch is rolled back
  console.error('Batch failed, all changes rolled back:', err)
}
```
