測試環境重置、資料遷移前清理、定期歸檔後清空。需求:清空所有使用者表、重置 Identity 種子、保留結構描述/索引/約束/權限。
DECLARE @SQL NVARCHAR(MAX) = N''
SELECT @SQL += N'TRUNCATE TABLE ' + QUOTENAME(SCHEMA_NAME(schema_id)) + N'.' + QUOTENAME(name) + N';'
FROM sys.tables
WHERE is_ms_shipped = 0
EXEC sp_executesql @SQL
⚠️ 限制:NVARCHAR(MAX) 理論 2GB,但極大量表(> 5000)可能超過批次大小或執行逾時。
DECLARE @TableName SYSNAME, @SchemaName SYSNAME, @SQL NVARCHAR(500)
DECLARE Cur CURSOR LOCAL FAST_FORWARD FOR
SELECT QUOTENAME(SCHEMA_NAME(schema_id)), QUOTENAME(name)
FROM sys.tables
WHERE is_ms_shipped = 0
ORDER BY schema_id, name
OPEN Cur
FETCH NEXT FROM Cur INTO @SchemaName, @TableName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @SQL = N'TRUNCATE TABLE ' + @SchemaName + N'.' + @TableName
BEGIN TRY
EXEC sp_executesql @SQL
PRINT 'Truncated: ' + @SchemaName + N'.' + @TableName
END TRY
BEGIN CATCH
PRINT 'FAILED: ' + @SchemaName + N'.' + @TableName + N' - ' + ERROR_MESSAGE()
END CATCH
FETCH NEXT FROM Cur INTO @SchemaName, @TableName
END
CLOSE Cur
DEALLOCATE Cur
優點:單表失敗不影響後續、可記錄日誌、可加條件篩選(如特定結構描述)。
EXEC sp_MSforeachtable 'TRUNCATE TABLE ?'
⚠️ 風險:Microsoft 未承諾支援、未來版本可能移除、無法 TRY/CATCH 個別表、無法篩選系統表/特定結構描述。
| 特性 | TRUNCATE TABLE | DELETE FROM |
|---|---|---|
| 日誌記錄 | 最小 (僅分頁釋放) | 完整 (逐列) |
| Identity 重置 | 自動重置為種子值 | 不重置 |
| 觸發器 | 不觸發 | 觸發 AFTER DELETE |
| 速度 | 極快 (元資料操作) | 慢 (逐列) |
| 權限需求 | ALTER 權限 | DELETE 權限 |
| 外鍵限制 | 被參考表不可 TRUNCATE | 可逐列刪除 (慢) |
-- 1. 停用所有外鍵
DECLARE @SQL NVARCHAR(MAX) = N''
SELECT @SQL += N'ALTER TABLE ' + QUOTENAME(SCHEMA_NAME(fk.schema_id)) + N'.' + QUOTENAME(OBJECT_NAME(fk.parent_object_id))
+ N' NOCHECK CONSTRAINT ' + QUOTENAME(fk.name) + N';'
FROM sys.foreign_keys fk
WHERE fk.is_ms_shipped = 0
EXEC sp_executesql @SQL
-- 2. 執行清空 (任選上述三法)
-- 3. 重新啟用外鍵 (WITH CHECK 確保現有資料符合)
SELECT @SQL = N''
SELECT @SQL += N'ALTER TABLE ' + QUOTENAME(SCHEMA_NAME(fk.schema_id)) + N'.' + QUOTENAME(OBJECT_NAME(fk.parent_object_id))
+ N' WITH CHECK CHECK CONSTRAINT ' + QUOTENAME(fk.name) + N';'
FROM sys.foreign_keys fk
WHERE fk.is_ms_shipped = 0
EXEC sp_executesql @SQL
CREATE PROCEDURE dbo.TruncateAllUserTables
@SchemaFilter SYSNAME = NULL, -- NULL 表示所有結構描述
@PrintOnly BIT = 0 -- 1 僅列印不執行
AS
BEGIN
SET NOCOUNT ON
DECLARE @SQL NVARCHAR(MAX) = N''
-- 停用 FK
SELECT @SQL += N'ALTER TABLE ' + QUOTENAME(SCHEMA_NAME(fk.schema_id)) + N'.' + QUOTENAME(OBJECT_NAME(fk.parent_object_id))
+ N' NOCHECK CONSTRAINT ' + QUOTENAME(fk.name) + N';'
FROM sys.foreign_keys fk
WHERE fk.is_ms_shipped = 0
AND (@SchemaFilter IS NULL OR SCHEMA_NAME(fk.schema_id) = @SchemaFilter)
IF @PrintOnly = 1 PRINT @SQL ELSE EXEC sp_executesql @SQL
-- 清空表
SET @SQL = N''
SELECT @SQL += N'TRUNCATE TABLE ' + QUOTENAME(SCHEMA_NAME(t.schema_id)) + N'.' + QUOTENAME(t.name) + N';'
FROM sys.tables t
WHERE t.is_ms_shipped = 0
AND (@SchemaFilter IS NULL OR SCHEMA_NAME(t.schema_id) = @SchemaFilter)
IF @PrintOnly = 1 PRINT @SQL ELSE EXEC sp_executesql @SQL
-- 啟用 FK
SET @SQL = N''
SELECT @SQL += N'ALTER TABLE ' + QUOTENAME(SCHEMA_NAME(fk.schema_id)) + N'.' + QUOTENAME(OBJECT_NAME(fk.parent_object_id))
+ N' WITH CHECK CHECK CONSTRAINT ' + QUOTENAME(fk.name) + N';'
FROM sys.foreign_keys fk
WHERE fk.is_ms_shipped = 0
AND (@SchemaFilter IS NULL OR SCHEMA_NAME(fk.schema_id) = @SchemaFilter)
IF @PrintOnly = 1 PRINT @SQL ELSE EXEC sp_executesql @SQL
END
-- 預覽將執行的指令
EXEC dbo.TruncateAllUserTables @PrintOnly = 1
-- 實際執行
EXEC dbo.TruncateAllUserTables
ALTER 權限,非 DELETE 權限