首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQLite REPLACE 語句深度解析:行級替換機制、主鍵驅動、與 UPDATE 差異對比及實戰驗證

     編輯:關於SqlServer

REPLACE 核心行為:DELETE + INSERT

SQLite REPLACE INTO 不是原地更新,而是:

  1. 根據主鍵/唯一約束衝突找到現有行。
  2. 刪除衝突行(觸發 DELETE 觸發器、外鍵級聯)。
  3. 插入新行(觸發 INSERT 觸發器、默認值、自增賦值)。

因此:行物理位置改變(通常移至表尾)、未指定列置為 NULL/默認值、Rowid 可能變化。

實戰驗證環境

CREATE TABLE student (
    id TEXT, name TEXT NOT NULL, sex TEXT, email TEXT UNIQUE,
    fenshu TEXT CHECK(fenshu > 0), tecid TEXT REFERENCES teacher(id),
    class TEXT, PRIMARY KEY (id, name) -- 復合主鍵
);

關鍵行為演示

操作SQL結果現象解析
完整替換REPLACE INTO student (id,name,sex,email,fenshu,tecid,class) VALUES ('2','lisi','*F','123@qq.com','80','2','1');原 id=2 行移至表尾,Rowid 變化DELETE+INSERT,物理位置改變
部分列替換REPLACE INTO student (id,name,sex,email,fenshu,tecid) VALUES ('2','lisi','*F','123@qq.com','80','2');class 列變為 NULL未指定列不保留舊值,按默認/NULL 填充
主鍵定位同上復合主鍵 (id,name) 唯一定位行REPLACE 依賴主鍵/唯一約束衝突判斷
無 WHERE 子句REPLACE ... WHERE id='2';語法錯誤REPLACE 不支持 WHERE,僅按值衝突
記錄不存在REPLACE INTO student ... VALUES ('100','a',...);直接插入新行無衝突等同 INSERT
唯一約束衝突觸發刪除其他行插入 email 重複行原有 email 相同行被刪除UNIQUE 衝突 → 刪除舊行 → 插入新行

REPLACE vs UPDATE 深度對比

維度REPLACEUPDATE
定位方式主鍵/唯一鍵值衝突WHERE 子句任意條件
影響行數0 或 1 (衝突時) / 1 (無衝突)0~N (滿足 WHERE 的所有行)
未指定列置 NULL/默認值保留原值
觸發器DELETE + INSERT 觸發器UPDATE 觸發器
外鍵級聯觸發 ON DELETE/INSERT 級聯觸發 ON UPDATE 級聯
Rowid/物理位置改變不變
性能較高開銷 (雙操作)較低 (原地修改)

適用場景與避坑指南

  • ✅ Upsert (Insert or Update):數據同步、增量導入、主鍵已知的覆蓋寫入。
  • ✅ 需觸發 DELETE/INSERT 邏輯:審計觸發器、級聯維護。
  • ❌ 批量更新多行:必須用 UPDATE + WHERE。
  • ❌ 保留未指定列舊值:必須用 UPDATE 或在 REPLACE 中顯式列出所有列。
  • ❌ 依賴 Rowid 穩定:REPLACE 會改變 Rowid,外鍵引用 Rowid 的表會斷裂。
  • ⚠️ 性能敏感場景:大批量 Upsert 考慮 INSERT ... ON CONFLICT DO UPDATE (SQLite 3.24.0+),單語句、原地更新、性能更優。

現代替代:ON CONFLICT 子句 (SQLite 3.24.0+)

INSERT INTO student (id,name,sex,email,fenshu,tecid,class)
VALUES ('2','lisi','*F','123@qq.com','80','2','1')
ON CONFLICT(id,name) DO UPDATE SET
    sex=excluded.sex, email=excluded.email, fenshu=excluded.fenshu,
    tecid=excluded.tecid, class=excluded.class;
-- 原地更新,保留 Rowid,僅更新指定列,性能最優
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved