將指定表的所有數據導出為 `INSERT INTO ... VALUES (...), (...), ...` 批量腳本,支持跨環境遷移、版本發布種子數據、測試數據快照。優於 SSMS「生成腳本」之處:純 T-SQL、可參數化調用、可集成到部署管線、支持大值類型分塊。
CREATE PROCEDURE dbo.usp_GenerateInsertScript
@SchemaName SYSNAME = 'dbo',
@TableName SYSNAME,
@BatchSize INT = 1000, -- 每批 VALUES 行數
@IncludeIdentity BIT = 1, -- 是否包含 IDENTITY 列 (需目標表 SET IDENTITY_INSERT ON)
@WhereClause NVARCHAR(MAX) = NULL, -- 可選過濾條件
@Script NVARCHAR(MAX) OUTPUT -- 返回腳本
AS
BEGIN
SET NOCOUNT ON;
DECLARE @FullName NVARCHAR(517) = QUOTENAME(@SchemaName) + '.' + QUOTENAME(@TableName);
DECLARE @Cols NVARCHAR(MAX), @ColList NVARCHAR(MAX), @Sql NVARCHAR(MAX);
DECLARE @HasIdentity BIT, @IdentityCol SYSNAME;
-- 1. 檢查表存在
IF OBJECT_ID(@FullName, 'U') IS NULL
BEGIN
RAISERROR('Table %s not found', 16, 1, @FullName);
RETURN -1;
END
-- 2. 收集列信息 (排除 timestamp、計算列、RowGuidCol 可選)
SELECT @Cols = COALESCE(@Cols + N', ', N'') + QUOTENAME(c.name),
@ColList = COALESCE(@ColList + N', ', N'') +
CASE
WHEN c.system_type_id IN (34, 35, 99, 241, 242) THEN -- image/text/ntext/xml/CLR UDT
N'CONVERT(NVARCHAR(MAX), ' + QUOTENAME(c.name) + N', 1)' -- 簡化演示,實際需分塊
WHEN c.system_type_id IN (165, 167, 173, 175, 231, 239) THEN -- char/varchar/binary/varbinary/nchar/nvarchar
N'''''''' + REPLACE(CONVERT(NVARCHAR(MAX), ' + QUOTENAME(c.name) + N'), N'''''', N'''''''''') + N'''''''
WHEN c.system_type_id IN (40, 41, 42, 43, 58, 59, 60, 61, 62, 106, 108, 122, 127) THEN -- 日期時間類
N'''''''' + CONVERT(NVARCHAR(MAX), ' + QUOTENAME(c.name) + N', 126) + N''''''' -- ISO8601
WHEN c.system_type_id IN (36, 48, 52, 56, 63, 104, 127) THEN -- 數值類
N'CONVERT(NVARCHAR(MAX), ' + QUOTENAME(c.name) + N')'
WHEN c.system_type_id = 104 THEN -- bit
N'CASE ' + QUOTENAME(c.name) + N' WHEN 1 THEN ''1'' ELSE ''0'' END'
ELSE N'NULL' -- 未知類型保守處理
END
FROM sys.columns c
JOIN sys.types t ON c.user_type_id = t.user_type_id
WHERE c.object_id = OBJECT_ID(@FullName)
AND c.is_computed = 0
AND t.name NOT IN ('timestamp', 'rowversion')
ORDER BY c.column_id;
-- 3. 標識列處理
SELECT @HasIdentity = 1, @IdentityCol = QUOTENAME(name)
FROM sys.columns
WHERE object_id = OBJECT_ID(@FullName) AND is_identity = 1;
IF @HasIdentity = 1 AND @IncludeIdentity = 0
BEGIN
-- 從列列表移除標識列
SET @Cols = REPLACE(@Cols, @IdentityCol + N', ', N'');
SET @Cols = REPLACE(@Cols, N', ' + @IdentityCol, N'');
SET @Cols = REPLACE(@Cols, @IdentityCol, N'');
-- 同步移除 @ColList 對應部分 (簡化:此處略過,實際需同步解析)
END
-- 4. 構建動態查詢 (分批輸出避免腳本過大)
SET @Sql = N'DECLARE @Batch INT = 0, @RowNum INT = 0, @Script NVARCHAR(MAX) = N'''';
SELECT @RowNum = COUNT(*) FROM ' + @FullName +
CASE WHEN ISNULL(@WhereClause, N'') = N'' THEN N'' ELSE N' WHERE ' + @WhereClause END + N';
WHILE @Batch * ' + CAST(@BatchSize AS NVARCHAR(10)) + N' < @RowNum
BEGIN
SELECT @Script = @Script +
N''INSERT INTO ' + @FullName + N' (' + @Cols + N') VALUES '' +
STUFF((
SELECT N'', ('' + ' + @ColList + N' + N'')''
FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS RN
FROM ' + @FullName +
CASE WHEN ISNULL(@WhereClause, N'') = N'' THEN N'' ELSE N' WHERE ' + @WhereClause END + N'
) t
WHERE t.RN BETWEEN @Batch * ' + CAST(@BatchSize AS NVARCHAR(10)) + N' + 1 AND (@Batch + 1) * ' + CAST(@BatchSize AS NVARCHAR(10)) + N'
FOR XML PATH(N''''), TYPE
).value(N''.[1]'', N''NVARCHAR(MAX)''), 1, 2, N'''') + N'';'' + CHAR(13) + CHAR(10);
SET @Batch = @Batch + 1;
END
SELECT @Script;';
EXEC sp_executesql @Sql, N'@Script NVARCHAR(MAX) OUTPUT', @Script OUTPUT;
END;
GO
DECLARE @Script NVARCHAR(MAX);
EXEC dbo.usp_GenerateInsertScript
@SchemaName = 'dbo',
@TableName = 'ConfigSettings',
@BatchSize = 500,
@IncludeIdentity = 1,
@WhereClause = 'Env = ''Prod''',
@Script = @Script OUTPUT;
-- 結果輸出到文件或打印
PRINT @Script; -- SSMS 結果窗口可能截斷,建議 sqlcmd -o 或 PowerShell Out-File
上述腳本對 `VARCHAR(MAX)`/`VARBINARY(MAX)`/`XML` 做簡化 `CONVERT`,實際生產建議:
| 工具/方法 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| SSMS Generate Scripts | GUI 易用、支持架構+數據、可選擇對象 | 大表極慢、易 OOM、難自動化 | 小表、手工一次性遷移 |
| bcp out / in | 極快、原生二進制、支持並行、格式文件可復用 | 需命令行、格式文件維護、不含 INSERT 語句 | 大數據量遷移、ETL 管線 |
| 本存儲過程 | 純 T-SQL、可參數化、可嵌入部署腳本、支持 WHERE 過濾 | 大值類型處理複雜、極大表腳本巨大 | 種子數據、配置表、中小業務表、CI/CD 管線 |
| SqlPackage / DACFx | 專業級、狀態比對、增量發布、支持 Azure SQL | 學習曲線、需 .NET 環境 | 項目級數據庫版本化部署 |