在 SQL Server 中清空資料表資料,最常用的兩個指令是 TRUNCATE TABLE 與 DELETE FROM table(無 WHERE 條件)。雖然結果皆為「移除所有資料列」,但底層機制、效能、日誌記錄與限制條件有本質差異。
| 特性 | TRUNCATE TABLE | DELETE |
|---|---|---|
| 執行速度 | 極快(僅記錄頁面釋放) | 較慢(逐列記錄刪除) |
| 交易日誌 | 最小化記錄(僅記錄分頁釋放) | 完整記錄每列刪除操作 |
| Identity 重置 | 自動重置 種子值 | 保留目前種子值 |
| 觸發器 | 不觸發 DELETE 觸發器 | 觸發 AFTER/INSTEAD OF DELETE |
| 外鍵限制 | 不可用 若被 FK 參考 | 可用(需符合 FK 規則) |
| WHERE 條件 | 不支援 | 支援條件式刪除 |
| 權限需求 | ALTER 權限 | DELETE 權限 |
| 資料頁鎖定 | 鎖定整張表與分頁 | 逐列鎖定(可升級為表鎖) |
| 回滾支援 | 支援(在交易中) | 支援 |
-- 建立測試表
CREATE TABLE dbo.TestTruncate (
ID INT IDENTITY(1,1) PRIMARY KEY,
DataCol VARCHAR(100)
);
INSERT INTO dbo.TestTruncate (DataCol) VALUES ('A'), ('B'), ('C');
-- Identity 目前種子 = 3
-- 使用 TRUNCATE
TRUNCATE TABLE dbo.TestTruncate;
-- Identity 重置為 1,下次插入 ID = 1
-- 重新插入測試
INSERT INTO dbo.TestTruncate (DataCol) VALUES ('X'), ('Y');
-- 使用 DELETE
DELETE FROM dbo.TestTruncate;
-- Identity 保持種子 = 3,下次插入 ID = 3
SQL Server 不允許直接 TRUNCATE 被 FK 參考的表。解決方案:
ALTER TABLE ChildTable NOCHECK CONSTRAINT FK_NameTRUNCATE TABLE ParentTableALTER TABLE ChildTable CHECK CONSTRAINT FK_Name或使用 DELETE FROM ParentTable 搭配 DBCC CHECKIDENT ('ParentTable', RESEED, 0) 手動重置 Identity。
優先使用 TRUNCATE TABLE 清空完整資料表,效能最佳、日誌最小、自動重置 Identity。僅在有外鍵、觸發器相依或需條件刪除時,改用 DELETE。