---
title: "Insert"
description: "Inserting data using Tauri SQLite ORM."
canonical_url: "https://docs.ctrl-neo.dev/en/tauri-sqlite-orm/querying-data/inserting-data"
---
# Insert

> Inserting data using Tauri SQLite ORM.

The `db.insert()` method is used to add new rows to a table. It returns a query builder for constructing the `INSERT` statement.

## Inserting a Single Row

To insert a single record, use the `.values()` method with a single object. After building the query, call `.execute()` to run it.

```ts
import { db } from '$lib/db';
import { users } from '$lib/db/schema';

// Type inference ensures you provide the correct properties.
// Optional columns (nullable or with defaults) can be omitted.
const newUser: InferInsertModel<typeof users> = {
  fullName: 'John Smith',
  email: 'john.smith@example.com',
};

const result = await db.insert(users).values(newUser).execute();

console.log(result);
// [{ rowsAffected: 1, lastInsertId: ... }]
```

<callout color="primary" icon="i-lucide-info">

**InferInsertModel**: This is a helper type that correctly represents the shape of an object for insertion, marking columns with default values or that are nullable as optional. See [Type Safety & Inference](https://docs.ctrl-neo.dev/6.advanced-topics/6.type-safety-and-inference) for more.

</callout>

## Inserting Multiple Rows

You can also insert multiple rows in a single, more efficient query by passing an array to `.values()`.

```ts
await db.insert(users).values([
  { fullName: 'Alice', email: 'alice@example.com' },
  { fullName: 'Bob', email: 'bob@example.com' },
]).execute();
```

## Returning Inserted Data

By default, an `INSERT` statement returns the number of affected rows and the last inserted ID. If you need the actual data from the newly created rows, you can use `.returning()`, `.returningAll()`, or `.returningFirst()`.

### `.returningFirst()` - Most Common Use Case

When inserting a single row, use `.returningFirst()` to get the inserted record directly without array destructuring:

```ts
// ✅ Clean and ergonomic
const insertedUser = await db.insert(users)
  .values({ fullName: 'Carol', email: 'carol@example.com' })
  .returningFirst();

console.log(insertedUser?.id); // The ID generated by the database
// Type: InferSelectModel<typeof users> | undefined
```

### `.returningAll()` - For Multiple Rows

When inserting multiple rows or when you always expect an array:

```ts
// Return all columns for the newly inserted users
const insertedUsers = await db.insert(users)
  .values([
    { fullName: 'Carol', email: 'carol@example.com' },
    { fullName: 'David', email: 'david@example.com' }
  ])
  .returningAll();

console.log(insertedUsers[0].id);
// Type: InferSelectModel<typeof users>[]
```

### `.returning()` - For Specific Columns

Return only the columns you need:

```ts
// Return only specific columns
const [insertedId] = await db.insert(users)
  .values({ fullName: 'David', email: 'david@example.com' })
  .returning('id');

console.log(insertedId); // { id: ... }
```

### Quick Comparison

```ts
// Old way - need array destructuring
const [user] = await db.insert(users).values(data).returningAll();

// New way - cleaner for single inserts
const user = await db.insert(users).values(data).returningFirst();
```

## Conflict Handling (UPSERT)

SQLite's `ON CONFLICT` clause is supported for handling cases where an insert would violate a `UNIQUE` or `PRIMARY KEY` constraint.

### `.onConflictDoNothing()`

If a conflict occurs (e.g., trying to insert a user with an email that already exists), this method will cause the `INSERT` operation to be silently ignored for that row.

```ts
// If a user with this email already exists, this query does nothing.
await db.insert(users)
  .values({ fullName: 'Jane Doe', email: 'jane.doe@example.com' })
  .onConflictDoNothing()
  .execute();
```

### `.onConflictDoUpdate()`

This enables "upsert" (update or insert) functionality. If a conflict occurs, it instead performs an `UPDATE` on the existing row.

```ts
// If a user with this email exists, update their name.
// Otherwise, insert a new user with this name and email.
await db.insert(users)
  .values({ fullName: 'John Smith (Updated)', email: 'john.smith@example.com'})
  .onConflictDoUpdate({
    target: users._.columns.email, // The column with the UNIQUE constraint
    set: {
      fullName: 'John Smith (Updated)', // Values to set on update
    }
  })
  .execute();
```

### Upsert Shorthand

For simple upserts, use the `.upsert()` helper:

```ts
// Insert or update user by email
await db.upsert(
  users,
  { fullName: 'John Doe', email: 'john@example.com' },
  ['email']  // Conflict target (unique column)
);
```


## Sitemap

See the full [sitemap](https://docs.ctrl-neo.dev/sitemap.md) for all pages.
