{
  "status": "shipping",
  "advantages": [],
  "limitations": [],
  "supersedes": [],
  "supersededBy": [],
  "firstSeen": null,
  "lastSeen": null,
  "updated": "2026-10-21",
  "slug": "sqlite-replace",
  "term": "SQLite REPLACE",
  "aliases": [
    "INSERT OR REPLACE"
  ],
  "definition": "SQLite REPLACE is a conflict-resolution algorithm that deletes rows conflicting with a UNIQUE or PRIMARY KEY constraint before completing the write.",
  "note": "REPLACE is not an in-place update. Its implicit conflict deletions invoke delete triggers only when recursive_triggers is enabled; foreign-key actions follow separate rules. [conflict] [foreign-keys]\n\nIn a SQLite 3.45.1 fixture, replacing parent ID 1 deleted both dependent rows under ON DELETE CASCADE, with recursive triggers either off or on. The final parent existed and both checks passed. A conflict-targeted UPSERT that changed only the label retained the children. [experiment] [data]\n\nChanging a referenced key or running other triggers can change an UPSERT's effects; not every UPSERT preserves dependents. CHECK or foreign-key violations are not repaired by REPLACE. [conflict] [upsert]\n\nOne incoming row can conflict with different existing rows through different unique keys. In twelve additional fixtures, incoming (1, beta) displaced parent 1 and parent 2, removing both sets of children. A label-only ON CONFLICT(id) update retained them; assigning the already-used code beta in DO UPDATE raised a UNIQUE error instead. The complete rows, settings and rollback controls are recorded. [multi-data]",
  "related": [
    "sqlite-foreign-key-action",
    "sqlite-foreign-key-check",
    "fts5-external-content"
  ],
  "citations": [
    {
      "id": "conflict",
      "title": "SQLite ON CONFLICT: REPLACE rules and exceptions",
      "url": "https://sqlite.org/lang_conflict.html",
      "accessed": "2026-10-21"
    },
    {
      "id": "foreign-keys",
      "title": "SQLite Foreign Key Support: actions and recursion limits",
      "url": "https://sqlite.org/foreignkeys.html",
      "accessed": "2026-10-21"
    },
    {
      "id": "upsert",
      "title": "SQLite UPSERT: conflict targets and DO UPDATE",
      "url": "https://sqlite.org/lang_upsert.html",
      "accessed": "2026-10-21"
    },
    {
      "id": "experiment",
      "title": "Hesela: REPLACE, foreign-key actions and complete reopened rows",
      "url": "https://hesela.com/analyses/sqlite-index-runtime-dependencies/#replace-foreign-keys",
      "accessed": "2026-10-21"
    },
    {
      "id": "data",
      "title": "Hesela: 24 matrix cases, four global-deferral controls and two orphan controls",
      "url": "https://hesela.dev/research/sqlite-replace-fk/results.json",
      "accessed": "2026-10-21"
    },
    {
      "id": "multi-data",
      "title": "Hesela: twelve two-unique-key write fixtures, complete rows and rollback trials",
      "url": "https://hesela.dev/research/sqlite-replace-fk/multi-unique-results.json",
      "accessed": "2026-10-21"
    }
  ],
  "provenance": [
    "Controlled software observations on SQLite 3.45.1; one INTEGER PRIMARY KEY conflict, single writer, DELETE and WAL. Not a crash test or failure-rate estimate.",
    "Two-key supplement: one INTEGER PRIMARY KEY and one BINARY-collated TEXT UNIQUE constraint; ON DELETE CASCADE, schema deferral on, global deferral off. Original single-key observations retained separately."
  ]
}
