# Upsert

本頁說明 `upsert()` 如何組出 `INSERT ... ON DUPLICATE KEY UPDATE`，以及第二個參數的三種形式。

## 基本用法

`upsert(data, updateData?)` 以 `data` 執行 INSERT；命中 PRIMARY KEY 或 UNIQUE 索引時改為更新（`src/MySQLPool.ts:316-360`）。

| 項目 | 行為 |
|---|---|
| 連線池 | 寫入池 |
| 回傳 | `insertId`；為 `0` 時回傳 `null` |
| `data` 的值 | 全部以佔位符綁定，不套用函式白名單 |

## `updateData` 的三種形式

| 形式 | 範例 | 產生的 UPDATE 子句 |
|---|---|---|
| 省略 | `upsert({ email: "e", name: "n" })` | `` `email` = VALUES(`email`), `name` = VALUES(`name`) `` |
| 物件 | `upsert({ email: "e" }, { updated_at: "NOW()", hits: 3 })` | `` `updated_at` = NOW(), `hits` = ? `` |
| 字串 | `upsert({ email: "e" }, "hits = hits + 1")` | `hits = hits + 1` |

```typescript
// 以 email 為唯一索引：不存在就新增，存在就累加次數並更新時間
await MySQLPool
  .table("subscribers")
  .upsert(
    { email: "john@example.com", hits: 1 },
    "hits = hits + 1, updated_at = NOW()"
  );
```

## 相關頁面

- [新增與更新](/zh/insert-and-update)
- [API 參考](/zh/api-reference)
