DuplicateItemException:重複的主索引鍵

TL;DR — PartiQL 的 INSERT 是嚴格的建立:如果已經存在具有相同主索引鍵的項目,DynamoDB 會拋出 DuplicateItemException 而不是覆寫它。要修改既有項目請用 PartiQL 的 UPDATE;若想要 PutItem 那種「存在就取代」的語意,就直接用 PutItem — PartiQL 的 INSERT 刻意永不取代。

這是什麼意思

DuplicateItemException: There was an attempt to insert an item with the
same primary key as an item that already exists in the DynamoDB table.

PartiQL 資料平面(ExecuteStatementExecuteTransactionBatchExecuteStatement)把 INSERT 對應成有條件的建立 — 只有在不存在具有該主索引鍵的項目時才會成功。這與原生 PutItem 的預設相反,後者會靜默地取代既有項目。如果你來自 SQL、預期 INSERT 在鍵重複時失敗,那這正是那個行為;如果你預期的是 upsert 語意,這個錯誤就是意外。

為什麼會發生

  • 項目確實已經存在 — 一次重試、一次重播,或兩個寫入者在同一個鍵上競賽而都發出了 INSERT
  • 你想要的是更新而不是建立 — 把 PutItem 風格的程式碼移植到 PartiQL,並假設 INSERT 會取代。
  • 非冪等的重試迴圈 — 第一次嘗試成功了但回應遺失(逾時),而重試又重新插入同一個鍵。
  • 合成的鍵並不唯一 — 你組出來的分割區/排序索引鍵碰撞的機率比你以為的高(例如精確度只到秒的時間戳)。

如何修正

  1. 要更新既有項目?使用 UPDATE

    UPDATE "orders" SET status = 'shipped' WHERE pk = 'ORDER#123' AND sk = 'META'
  2. 想要「存在就取代」(PutItem 語意)?就呼叫 PutItem — PartiQL 沒有 upsert 陳述式,而原生 API 的預設行為正是你想要的那種覆寫:

    await client.send(new PutItemCommand({TableName: 'orders', Item: item}));
  3. 當建立是冪等的,就把它當成成功 — 如果重試對一個你第一次嘗試就已寫入的項目碰到 DuplicateItemException,捕捉並忽略它通常才是正確的處理方式。

  4. 當你倚賴唯一性時就保留 INSERT — 這個例外就是你的「只建立」防護,相當於 PartiQL 版本的 PutItem 條件式 attribute_not_exists()

要內化 INSERTUPDATE 的區別,最快的方法就是拿真實資料試跑陳述式 — DynoTable 的 PartiQL 編輯器可對你的線上資料表執行陳述式並提供行內診斷與快速修正,而當你需要 PutItem 語意時,DynamoDB Expression Builder 會產出等價的原生 API 請求。

重現方式

對一個已存在的主索引鍵執行 PartiQL INSERT

await client.send(
  new PutItemCommand({
    TableName: 'orders',
    Item: {pk: {S: 'ORDER#1'}, sk: {S: 'META'}}
  })
);
await client.send(
  new ExecuteStatementCommand({
    Statement: `INSERT INTO "orders" VALUE {'pk':'ORDER#1','sk':'META'}`
  })
);

實際輸出:

DuplicateItem: Duplicate primary key exists in table
HTTP 400

如果你在本機測試,這點值得知道:DynamoDB Local 會以 DuplicateItem 加上方那句簡短訊息呈現,而服務端的 API 參考文件則記載為 DuplicateItemException 並附上較長的句子。請比對 HTTP 400 加上操作本身,而不是確切的名稱或用字,否則你的處理程式在 Local 與真實資料表上的行為會不一樣。

相關錯誤

參考資料

最後於 2026-07-13 對照上方連結的官方 AWS 文件驗證。

已於 2026-07-26 對照 DynamoDB Local 2.x 與 AWS SDK for JavaScript v3.1095.0 重現 — 上方輸出為逐字原文。

不必透過主控台就能操作 DynamoDB

一款快速的 DynamoDB 桌面用戶端,可執行 DynamoDB 無法執行的真正 SQL — JOINs、GROUP BY、聚合 — 並支援視覺化編輯與使用你自己的 Bedrock 金鑰的 AI 代理。

30 天免費試用,無需信用卡 — 之後為無時間限制的免費方案。