【问题标题】:Insert Large data row by row in multiple reference tables在多个引用表中逐行插入大数据
【发布时间】:2019-05-24 06:50:33
【问题描述】:

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

我们有一种情况,我们希望将sqlserver 2017 上的大型数据集存储到多个参考表中。

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

示例

T_Bulk 是输入表,T_Bulk_Orignal 是目标表,T_Bulk_referencet_Bulk_orignal 的参考表

    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

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

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

请就此提出最佳方法

【问题讨论】:

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


    【解决方案1】:

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

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

    我已经在 50+ 百万行上完成了与您类似的工作。

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

    【讨论】:

    • 我们希望在 C# 应用程序级别拥有它。我认为 SSIS 将在我们的赛道计划中有所改变。
    【解决方案2】:

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

    SQL 中存在Merge 语句。

    MERGE 语句用于根据 从花药匹配的值。它可以用来组合插入, 更新和删除操作合并到一个语句中

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-21
      • 2017-08-13
      • 2021-08-22
      相关资源
      最近更新 更多