在多个参考表中逐行插入大数据

时间:2019-05-24 06:50:34

标签: sql sql-server tsql sql-server-2016 bulkinsert

  

我在 SO 上浏览了很多帖子。但是,它们不适合我的情况。

在某些情况下,我们要将sqlserver 2017上的大型数据集存储到多个参考表中。

我们已经尝试使用cursor,并且工作正常。但是,我们担心加载大数据(1+百万行)的性能问题

  

示例

     

T_Bulk 是一个输入表, T_Bulk_Orignal 是目标表, T_Bulk_reference t_Bulk_orignal < / p>

    create table T_Bulk
(
Id uniqueidentifier,
ElementType nvarchar(max),
[Description] nvarchar(max)
)

create table T_Bulk_orignal
(
Id uniqueidentifier,
ElementType nvarchar(max),
[Description] nvarchar(max)
)

create table T_Bulk_reference
(
Id uniqueidentifier,
Description2 nvarchar(max)
)

create proc UseCursor
(
@udtT_Bulk as dbo.udt_T_Bulk READONLY
)
as
begin 


DECLARE @Id uniqueidentifier, @ElementType varchar(500), @Description varchar(500),@Description2 varchar(500)

    DECLARE MY_CURSOR CURSOR 
    LOCAL STATIC READ_ONLY FORWARD_ONLY  
    FOR   
    SELECT Id, ElementType, [Description]
    FROM dbo.T_BULK


    OPEN MY_CURSOR  
    FETCH NEXT FROM MY_CURSOR INTO @Id, @ElementType, @Description,@Description2
    WHILE @@FETCH_STATUS = 0  
    BEGIN   

    BEGIN Transaction Trans1

    BEgin TRy

            IF EXISTS (select Id from T_Bulk_orignal where ElementType=@ElementType and Description=@Description)
                select @Id = Id from T_Bulk_orignal where ElementType=@ElementType and Description=@Description

            ELSE
                BEGIN
                    insert T_Bulk_orignal(Id,ElementType,Description) values (@id, @ElementType,@Description)
                END


            INSERT T_Bulk_reference(Id,description2) 
            SELECT Id, Description2   
            FROM (select @Id as Id, @Description2 as Description2) F
            WHERE NOT EXISTS (SELECT * FROM T_Bulk_reference C WHERE C.Id = F.Id and C.Description2 = F.Description2);

    COMMIT TRANSACTION [DeleteTransaction]

        FETCH NEXT FROM MY_CURSOR INTO @Id, @ElementType, @Description,@Description2
    END TRY
    BEGIN CATCH

                    ROLLBACK TRANSACTION [Trans1]

                    SELECT @@Error

    END CATCH   
    END  

    CLOSE MY_CURSOR  
    DEALLOCATE MY_CURSOR

end
  

我们希望此操作像批量插入一样一次性执行,但是我们还需要交叉检查任何数据差异,如果无法插入一行,我们只需要回滚该特定记录

批量插入的唯一障碍是存在参考表数据。

请为此建议最佳方法

2 个答案:

答案 0 :(得分:0)

这听起来像是SSIS(SQL Server Integration Services)的工作。 https://docs.microsoft.com/en-us/sql/integration-services/ssis-how-to-create-an-etl-package

在SSIS中,您可以创建可以进行引用检查的数据迁移作业。您可以将其设置为在每个阶段失败,警告或忽略错误。要在此Google上查找ETL和SSIS的资源。

我完成了超过50百万行的像您一样的工作。

当然要花一些时间,并且会在出现错误时回滚所有内容(如果这样设置),但这是进行此类工作的最佳工具。

答案 1 :(得分:0)

我有一个解决方案,可以像批量插入一样上传大型文件。

SQL中存在一个Merge语句。

  

MERGE语句用于根据以下内容在一个表中进行更改   从花药匹配的值。它可以用于结合插入,   更新和删除操作成一条语句

因此我们可以使用DataTable将数据传递到StoredProcedure,然后Source将是您的UserDefinedDataTable,而Target将是您实际的SQL Table