如何在SQL Server中将大量数据从一个表复制到另一个表
我想将大量数据从一个表复制到另一个表。我在存储过程中使用了游标来执行同样的操作。但它只适用于记录较少的表。如果表包含更多记录,它将执行很长时间并被挂起。请给出一些建议,说明如何更快地复制数据,我的SP如下所示:如何在SQL Server中将大量数据从一个表复制到另一个表,sql,Sql,我想将大量数据从一个表复制到另一个表。我在存储过程中使用了游标来执行同样的操作。但它只适用于记录较少的表。如果表包含更多记录,它将执行很长时间并被挂起。请给出一些建议,说明如何更快地复制数据,我的SP如下所示: --exec uds_shop --select * from CMA_UDS.dbo.Dim_Shop --select * from UDS.dbo.Dim_Shop --delete from CMA_UDS.dbo.Dim_Shop alter procedure uds_s
--exec uds_shop
--select * from CMA_UDS.dbo.Dim_Shop
--select * from UDS.dbo.Dim_Shop
--delete from CMA_UDS.dbo.Dim_Shop
alter procedure uds_shop
as
begin
declare @dwkeyshop int
declare @shopdb int
declare @shopid int
declare @shopname nvarchar(60)
declare @shoptrade int
declare @dwkeytradecat int
declare @recordowner nvarchar(20)
declare @LogMessage varchar(600)
Exec CreateLog 'Starting Process', 1
DECLARE cur_shop CURSOR FOR
select
DW_Key_Shop,Shop_ID,Shop_Name,Trade_Sub_Category_Code,DW_Key_Source_DB,DW_Key_Trade_Category,Record_Owner
from
UDS.dbo.Dim_Shop
OPEN cur_shop
FETCH NEXT FROM cur_shop INTO @dwkeyshop,@shopid,@shopname,@shoptrade, @shopdb ,@dwkeytradecat,@recordowner
WHILE @@FETCH_STATUS = 0
BEGIN
Set @LogMessage = ''
Set @LogMessage = 'Records insertion/updation start date and time : ''' + Convert(varchar(19), GetDate()) + ''''
if (isnull(@dwkeyshop, '') <> '')
begin
if not exists (select crmshop.DW_Key_Shop from CMA_UDS.dbo.Dim_Shop as crmshop where (convert(varchar,crmshop.DW_Key_Shop)+CONVERT(varchar,crmshop.DW_Key_Source_DB)) = convert(varchar,(CONVERT(varchar, @dwkeyshop) + CONVERT(varchar, @shopdb))) )
begin
Set @LogMessage = Ltrim(Rtrim(@LogMessage)) + ' ' + 'Record for shop table is inserting...'
insert into
CMA_UDS.dbo.Dim_Shop
(DW_Key_Shop,DW_Key_Source_DB,DW_Key_Trade_Category,Record_Owner,Shop_ID,Shop_Name,Trade_Sub_Category_Code)
values
(@dwkeyshop,@shopdb,@dwkeytradecat,@recordowner,@shopid,@shopname,@shoptrade)
Set @LogMessage = Ltrim(Rtrim(@LogMessage)) + ' ' + 'Record successfully inserted in shop table for shop Id : ' + Convert(varchar, @shopid)
end
else
begin
Set @LogMessage = Ltrim(Rtrim(@LogMessage)) + ' ' + 'Record for Shop table is updating...'
update
CMA_UDS.dbo.Dim_Shop
set DW_Key_Trade_Category=@dwkeytradecat,
Record_Owner=@recordowner,
Shop_ID=@shopid,Shop_Name=@shopname,Trade_Sub_Category_Code=@shoptrade
where
DW_Key_Shop=@dwkeyshop and DW_Key_Source_DB=@shopdb
Set @LogMessage = Ltrim(Rtrim(@LogMessage)) + ' ' + 'Record successfully updated for shop Id : ' + Convert(varchar, @shopid)
end
end
Exec CreateLog @LogMessage, 0
FETCH NEXT FROM cur_shop INTO @dwkeyshop,@shopid,@shopname,@shoptrade, @shopdb ,@dwkeytradecat,@recordowner
end
CLOSE cur_shop
DEALLOCATE cur_shop
End
根据我个人的经验,当您将具有类似约束的巨大数据从一个表复制到另一个表时,请将约束放在复制数据的表上。复制完成后,再次恢复所有约束 假设targetTable和destinationTable具有相同的模式,我可以将复制时间从7小时减少到30分钟,在我的情况下,有6个约束的1亿条记录
INSERT INTO targetTable t
SELECT * FROM destinationTable d
WHERE someCriteria
除非没有其他方法,否则避免使用游标
您可以使用WHERE子句过滤掉任何重复记录
如果有标识列,请使用不包含标识列的显式列列表
您还可以尝试禁用约束和删除索引,前提是替换它们并确保随后检查约束
如果您使用的是SQL Server 2008以后的版本,则可以使用该语句。游标速度非常慢,对于非常大的数据集,ram可能开始成为一个问题 看起来您在每个迭代中都做了大量的日志记录,因此您可能会被光标卡住,但我会寻找一种方法将作业分解为多个调用,这样您就可以保持较小的占用空间
如果您有一个autonumber列,我会在过程中添加一个'@startIdx bigint',并重新定义游标语句,以获取'TOP 1000',其中[autonumberFeild]你的源表有标识列吗?我的源表中没有标识列。谢谢你的回答。在30分钟内移动数百万条记录是非常困难的。我已经得到了要求,因为我不想截断每个表并插入,因为这可能会影响。你能请你更详细地了解我在SP中必须遵循的内容吗?我的源表没有有任何主键,而我的目标表有主键。请解释。您好,我尝试了您的,我在筛选where条件时遇到了一些困难,因为我将比较两列以获得唯一值,您可以在我的查询中看到,从CMA_UDS.dbo.Dim_Shop中选择crmshop.DW_Key_Shop作为crmshop where convertvarchar,crmshop.DW_Key_Shop+CONVERTvarchar,crmshop.DW_Key_Source_DB=CONVERTvarchar,CONVERTvarchar,@dwkeyshop+CONVERTvarchar,@shopdb你能解释一下与@MitchWheat的答案相比的附加值吗,特别是因为move是错误的。
DECLARE @startIdx bigint = 0
WHILE select COUNT(*) FROM <sourceTable> > @startIdx
BEGIN
EXEC <your stored procedure> @startIdx
END
SET @startIdx = @startIdx + 1000
INSERT INTO targetTable
SELECT * FROM destinationTable
WHERE someCriteria (based on Criteria you can copy/move the records)