我喜欢@Mathieu Longtin 的解决方案,可以批量复制,从而最大限度地减少日志文件问题,并按照@CervEd 的建议创建了一个带有OFFSET FETCH 的版本。
其他人建议使用导入/导出向导或 SSIS 包,但这并不总是可行的。
这对许多人来说可能有点矫枉过正,但我的解决方案还包括对记录数和输出进度的一些检查。
USE [MyDB]
GO
SET NOCOUNT ON;
DECLARE @intStart int = 1;
DECLARE @intCount int;
DECLARE @intFetch int = 10000;
DECLARE @strStatus VARCHAR(200);
DECLARE @intCopied int = 0;
SET @strStatus = CONVERT(VARCHAR(30), GETDATE()) + ' Getting count of HISTORY records currently in MyTable...';
RAISERROR (@strStatus, 10, 1) WITH NOWAIT;
SELECT @intCount = COUNT(*) FROM [dbo].MyTable WHERE IsHistory = 1;
SET @strStatus = CONVERT(VARCHAR(30), GETDATE()) + ' Count of HISTORY records currently in MyTable: ' + CONVERT(VARCHAR(20), @intCount);
RAISERROR (@strStatus, 10, 1) WITH NOWAIT; --(note: PRINT resets @@ROWCOUNT to 0 so using RAISERROR instead)
SET @strStatus = CONVERT(VARCHAR(30), GETDATE()) + ' Starting copy...';
RAISERROR (@strStatus, 10, 1) WITH NOWAIT;
WHILE @intStart < @intCount
BEGIN
INSERT INTO [dbo].[MyTable_History] (
[PK1], [PK2], [PK3], [Data1], [Data2])
SELECT
[PK1], [PK2], [PK3], [Data1], [Data2]
FROM [MyDB].[dbo].[MyTable]
WHERE IsHistory = 1
ORDER BY
[PK1], [PK2], [PK3]
OFFSET @intStart - 1 ROWS
FETCH NEXT @intFetch ROWS ONLY;
SET @intCopied = @intCopied + @@ROWCOUNT;
SET @strStatus = CONVERT(VARCHAR(30), GETDATE()) + ' Records copied so far: ' + CONVERT(VARCHAR(20), @intCopied);
RAISERROR (@strStatus, 10, 1) WITH NOWAIT;
SET @intStart = @intStart + @intFetch;
END
--Check the record count is correct.
IF @intCopied = @intCount
BEGIN
SET @strStatus = CONVERT(VARCHAR(30), GETDATE()) + ' Correct record count.';
RAISERROR (@strStatus, 10, 1) WITH NOWAIT;
END
ELSE
BEGIN
SET @strStatus = CONVERT(VARCHAR(30), GETDATE()) + ' Only ' + CONVERT(VARCHAR(20), @intCopied) + ' records were copied, expected: ' + CONVERT(VARCHAR(20), @intCount);
RAISERROR (@strStatus, 10, 1) WITH NOWAIT;
END
GO