# INSERT — write an item (and resolve conflicts)

Write one item as a PartiQL object literal. A plain `INSERT` over an existing primary key is **refused by DynamoDB itself** — it never silently overwrites; `ON CONFLICT` says what to do *instead*, and each form lowers to the one native write it maps onto. Writes run on the first press (no preview ritual) and a read-only stage refuses them at the dispatch layer.

## Syntax

```sql
INSERT INTO "table"
VALUE { 'attr': value, … }              -- a PartiQL object literal
[ON CONFLICT [(pk[, sk])]
  DO NOTHING | DO REPLACE | DO UPDATE SET assignments]
```

String keys, typed values; nested maps and lists follow the same literal syntax. The conflict target is **always the primary key** — DynamoDB has no uniqueness anywhere else, so a non-key target refuses before the wire. Guide: [Writes & transactions](https://www.kanject.com/docs/dynostudio-partiql-writes/).

## Use cases

### Create an item

Seed a user profile, stamped with the write instant — clock functions render **UTC** literals at run time.

```sql
INSERT INTO "stage.Users"
VALUE {'pk': 'USER#42', 'sk': 'PROFILE', 'Name': 'Ada',
       'CreatedAt': CURRENT_TIMESTAMP}
```

_Executes as:_ PutItem · condition: key must not already exist

- If `USER#42 / PROFILE` already exists, the insert refuses — reach for `ON CONFLICT` below to say what should happen instead.

_Quote this example:_ https://www.kanject.com/docs/dynostudio-insert/#seed-item

### Insert only if absent (idempotent create)

Safe to retry, safe to race: an existing key is a **counted skip**, not an error.

```sql
INSERT INTO "stage.Users"
VALUE {'pk': 'USER#42', 'sk': 'PROFILE', 'Name': 'Ada'}
ON CONFLICT DO NOTHING
```

_Executes as:_ PutItem · guarded by attribute_not_exists

_Quote this example:_ https://www.kanject.com/docs/dynostudio-insert/#insert-if-absent

### Replace the whole item

Overwrite whatever is stored under the key — the effect a plain INSERT refuses to have, made explicit.

```sql
INSERT INTO "stage.Users"
VALUE {'pk': 'USER#42', 'sk': 'PROFILE', 'Name': 'Ada L.'}
ON CONFLICT DO REPLACE
```

_Executes as:_ PutItem · unguarded — the stored item is replaced entirely

- **Replaces the whole item**, not just the named attributes — anything the new literal omits is gone.

_Quote this example:_ https://www.kanject.com/docs/dynostudio-insert/#replace-item

### Upsert a counter (create or increment)

The first visit creates the row with `visits = 1`; every later one increments — **one atomic native write** covers both.

```sql
INSERT INTO "stage.Users"
VALUE {'pk': 'USER#42', 'sk': 'PROFILE', 'visits': 1}
ON CONFLICT DO UPDATE SET visits = if_not_exists(visits, 0) + 1
```

_Executes as:_ UpdateItem · native upsert — VALUE attributes seed a fresh row via if_not_exists

- Write `if_not_exists(visits, 0) + 1`, not `visits + 1` — on a freshly created row the bare attribute doesn't exist yet, so there's nothing to add to.

_Quote this example:_ https://www.kanject.com/docs/dynostudio-insert/#upsert-counter

### Create a self-expiring item

A session row DynamoDB's TTL sweeper will delete in 7 days — epoch **seconds**, a bare number; an ISO string never matches.

```sql
INSERT INTO "stage.Sessions"
VALUE {'pk': 'Session#42', 'sk': 'META',
       'ExpiresAt': unix_now() + 604800}
```

_Executes as:_ PutItem · unix_now() + 604800 folds to an epoch-seconds literal before the wire

_Quote this example:_ https://www.kanject.com/docs/dynostudio-insert/#insert-with-ttl

## Try it

**Try it · INSERT**

```sql
INSERT INTO "stage.Users"
VALUE {'pk': 'USER#42', 'sk': 'PROFILE', 'visits': 1}
ON CONFLICT DO UPDATE SET visits = if_not_exists(visits, 0) + 1
```

_Executes as:_ UpdateItem · stage.Users — One atomic write, whether the row exists or not — the VALUE attributes seed a fresh row. Disclosed like every lowering: the strip shows the exact native form before you run.

_Result:_ ✓ 1 item written · visits = 4 · 1 WCU

_Run it live in DynoStudio:_ https://www.kanject.com/dynostudio/

> **DO REPLACE is item-wide:** `DO UPDATE SET` changes the named attributes and keeps the rest; `DO REPLACE` swaps in the **entire new literal** — attributes the literal omits are deleted. If you mean "update these fields", say `DO UPDATE`.

Related: [Writes & transactions](https://www.kanject.com/docs/dynostudio-partiql-writes/) · [UPDATE](https://www.kanject.com/docs/dynostudio-update/) · [Transactions](https://www.kanject.com/docs/dynostudio-transactions/) · [keyword reference](https://www.kanject.com/docs/dynostudio-partiql-keywords/).

---
_Source: https://www.kanject.com/docs/dynostudio-insert/ · Kanject Docs_
