好的。
这是我的样本。
发生在我身上的是我的 dba “团队” .. 搞砸了为我们设置复制。所以..在周末,像狗一样工作....我们不得不编写一些代码来将记录从源数据库“拉”到目标数据库,其中数据库的结构是相同的。我们不得不伪造一些复制。
我们有 8,000,000 行,我们一次会将它们拉到 10,000 多个。下面,我有大约 1000 行,并将“一次拉取的行数”设置为 333。我还放置了一个 @MaximumLoopCounter 作为“以防万一”。我不想意外地创建一个无限循环。
下面的示例将其“while”逻辑基于“while exists(源数据库表上的一些记录不在目标数据库表中)”......继续抓取这些记录。
我试图帮助你回答你的问题。在我们的例子中,我们最终让复制工作正常,并且我们能够放弃这些脚本。这不是一个有趣的周末。
/* 设置 */
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[CodeCategorySourceTable]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
BEGIN
DROP TABLE [dbo].[CodeCategorySourceTable]
END
GO
CREATE TABLE [dbo].[CodeCategorySourceTable] (
CodeCategoryUUID [uniqueidentifier] not null default NEWSEQUENTIALID() ,
CodeCategoryName varchar(64) not null
)
GO
ALTER TABLE [dbo].[CodeCategorySourceTable] ADD CONSTRAINT PK_CodeCategorySourceTable_CodeCategoryUUID
PRIMARY KEY CLUSTERED (CodeCategoryUUID)
GO
ALTER TABLE [dbo].[CodeCategorySourceTable] ADD CONSTRAINT CK_CodeCategorySourceTable_CodeCategoryName_UNIQUE
UNIQUE (CodeCategoryName)
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[CodeCategoryDestinationTable]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
BEGIN
DROP TABLE [dbo].[CodeCategoryDestinationTable]
END
GO
CREATE TABLE [dbo].[CodeCategoryDestinationTable] (
CodeCategoryUUID [uniqueidentifier] not null default NEWSEQUENTIALID() ,
CodeCategoryName varchar(64) not null
)
GO
ALTER TABLE [dbo].[CodeCategoryDestinationTable] ADD CONSTRAINT PK_CodeCategoryDestinationTable_CodeCategoryUUID
PRIMARY KEY CLUSTERED (CodeCategoryUUID)
GO
ALTER TABLE [dbo].[CodeCategoryDestinationTable] ADD CONSTRAINT CK_CodeCategoryDestinationTable_CodeCategoryName_UNIQUE
UNIQUE (CodeCategoryName)
GO
declare @AlreadyExistingCodeCategoryUUID01 uniqueidentifier
declare @AlreadyExistingCodeCategoryUUID03 uniqueidentifier
declare @AlreadyExistingCodeCategoryUUID02 uniqueidentifier
declare @AlreadyExistingOldCodeCategoryName01 varchar(64)
declare @AlreadyExistingOldCodeCategoryName02 varchar(64)
declare @AlreadyExistingOldCodeCategoryName03 varchar(64)
declare @AlreadyExistingNewCodeCategoryName01 varchar(64)
declare @AlreadyExistingNewCodeCategoryName02 varchar(64)
declare @AlreadyExistingNewCodeCategoryName03 varchar(64)
select @AlreadyExistingCodeCategoryUUID01 = NEWID(), @AlreadyExistingCodeCategoryUUID02 = NEWID(), @AlreadyExistingCodeCategoryUUID03 = NEWID()
select @AlreadyExistingNewCodeCategoryName01 = 'NewOne', @AlreadyExistingNewCodeCategoryName02 = 'NewTwo', @AlreadyExistingNewCodeCategoryName03 = 'NewThree'
select @AlreadyExistingOldCodeCategoryName01 = 'OldOne', @AlreadyExistingOldCodeCategoryName02 = 'OldTwo', @AlreadyExistingOldCodeCategoryName03 = 'OldThree'
Insert Into [dbo].[CodeCategorySourceTable] ( CodeCategoryUUID , CodeCategoryName )
Select top 1000 NEWID() , convert(varchar(40), NEWID()) + 'Name' from dbo.sysobjects so1 cross join dbo.sysobjects so2
Insert Into [dbo].[CodeCategorySourceTable] ( CodeCategoryUUID , CodeCategoryName )
select @AlreadyExistingCodeCategoryUUID01, @AlreadyExistingNewCodeCategoryName01
UNION ALL select @AlreadyExistingCodeCategoryUUID02, @AlreadyExistingNewCodeCategoryName02
UNION ALL select @AlreadyExistingCodeCategoryUUID03, @AlreadyExistingNewCodeCategoryName03
select count(*) from [dbo].[CodeCategorySourceTable] as CodeCategorySourceTableCOUNT
Insert Into [dbo].[CodeCategoryDestinationTable] ( CodeCategoryUUID , CodeCategoryName )
select @AlreadyExistingCodeCategoryUUID01, @AlreadyExistingOldCodeCategoryName01
UNION ALL select @AlreadyExistingCodeCategoryUUID02, @AlreadyExistingOldCodeCategoryName02
UNION ALL select @AlreadyExistingCodeCategoryUUID03, @AlreadyExistingOldCodeCategoryName03
select count(*) from [dbo].[CodeCategoryDestinationTable] as CodeCategoryDestinationTableCOUNT
/* 美国药典 */
print '[uspCodeCategoryReplicateReplacer]'
go
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[uspCodeCategoryReplicateReplacer]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[uspCodeCategoryReplicateReplacer]
Go
/*
declare @numberRowsAffected int
declare @ErrorNumber int
exec [dbo].[uspCodeCategoryReplicateReplacer] @numberRowsAffected output , @ErrorNumber output
print @numberRowsAffected
print @ErrorNumber
print ''
*/
CREATE PROCEDURE [dbo].[uspCodeCategoryReplicateReplacer] (
@numberRowsAffected int output
,
@ErrorNumber int output
)
AS
SET NOCOUNT ON
select @ErrorNumber = 0
declare @ErrorTracker int
declare @insertRowCount int
declare @updateRowCount int
select @insertRowCount = 0
select @updateRowCount = 0
declare @CurrentInsertCount int
declare @ManualReplicationRowCount int
select @ManualReplicationRowCount = 333
declare @MaximumLoopCounter int
select @MaximumLoopCounter = 10000
while (@MaximumLoopCounter > 0) and exists
(
Select
TOP 1 null
from [dbo].[CodeCategorySourceTable] sourceTable with (nolock)
where not exists
(
select null from [dbo].[CodeCategoryDestinationTable] destinationTable with (nolock)
Where
destinationTable.CodeCategoryUUID = sourceTable.CodeCategoryUUID
)
)
BEGIN
select @MaximumLoopCounter = @MaximumLoopCounter - 1
/* DELETE FROM [dbo].[CodeCategoryDestinationTable] */
SET NOCOUNT OFF
Insert into [dbo].[CodeCategoryDestinationTable]
(
CodeCategoryUUID,
CodeCategoryName
)
Select
TOP (@ManualReplicationRowCount)
CodeCategoryUUID,
CodeCategoryName
from [dbo].[CodeCategorySourceTable] sourceTable with (nolock)
where not exists
(
select null from [dbo].[CodeCategoryDestinationTable] destinationTable with (nolock)
Where
destinationTable.CodeCategoryUUID = sourceTable.CodeCategoryUUID
)
SELECT @CurrentInsertCount = @@ROWCOUNT , @ErrorTracker = @@ERROR
select @insertRowCount = @insertRowCount + @CurrentInsertCount
if @ErrorTracker <> 0
BEGIN
select @ErrorNumber = @ErrorTracker
select @MaximumLoopCounter = 0 /*Bail Out !!!*/
END
SET NOCOUNT ON
END /*End While Loop*/
print '/Before Look [dbo].[CodeCategoryDestinationTable] */'
select * from [dbo].[CodeCategoryDestinationTable]
SET NOCOUNT OFF
/* A little extra. Update any non-surrogate-key values... We did not do this, but I leave it here as for kicks */
Update [dbo].[CodeCategoryDestinationTable]
Set
/*CodeCategoryUUID = vart.CodeCategoryUUID,*/
CodeCategoryName = sourceTable.CodeCategoryName
From
[dbo].[CodeCategoryDestinationTable] destinationTable, [dbo].[CodeCategorySourceTable] sourceTable
Where
/*Relationship*/
destinationTable.CodeCategoryUUID = sourceTable.CodeCategoryUUID
/*Filter*/
and destinationTable.CodeCategoryName <> sourceTable.CodeCategoryName
SELECT @updateRowCount = @@ROWCOUNT
SET NOCOUNT ON
print '/After Look [dbo].[CodeCategoryDestinationTable] */'
select * from [dbo].[CodeCategoryDestinationTable]
print '/@insertRowCount COUNT/'
print @insertRowCount
print '-------------------------'
print '/@updateRowCount COUNT/'
print @updateRowCount
print '-------------------------'
SELECT @numberRowsAffected = @insertRowCount + @updateRowCount
print '/ [dbo].[CodeCategoryDestinationTable] COUNT/'
print @numberRowsAffected
print '-------------------------'
SET NOCOUNT OFF
GO
/*GRANT EXECUTE ON dbo.uspCodeCategoryReplicateReplacer TO $(DBUSERNAME)*/
GO
/* 改进,封装 ManualReplicationRowCount “getter”,以便在一处更改 */
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[uspInternalSettingGetManualReplicationRowCount]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[uspInternalSettingGetManualReplicationRowCount]
GO
/*
--START TEST
declare @returnCode int
declare @ManualReplicationRowCount int
EXEC @returnCode = dbo.uspInternalSettingGetManualReplicationRowCount @ManualReplicationRowCount output
print @ManualReplicationRowCount
print '/@returnCode/'
print @returnCode
*/
CREATE PROCEDURE [dbo].[uspInternalSettingGetManualReplicationRowCount] (
@ManualReplicationRowCount int output --return
)
AS
SET NOCOUNT ON
select @ManualReplicationRowCount = 333
SET NOCOUNT OFF
GO