2016-12-16 155 views
0

我很好奇,如果任何人都可以建议一个更好的方式来做批量插入。在我目前的工作中,我们构建了作为变量传递给存储过程的xml字符串,然后创建一个临时表并插入xml。很多时候我看到一个游标正在使用哪个我更喜欢如果可能的话批量插入SQL Server

DECLARE @DriverToImport TABLE 
     (DriverId INT NULL DEFAULT (0), 
     IsNew TINYINT NOT NULL DEFAULT (0), 
     DriverExternalId NVARCHAR(20) NOT NULL, 
     DriverName NVARCHAR(100) NOT NULL, 
     HireDate SMALLDATETIME NULL, 
     HomeNumber NVARCHAR(20) NULL, 
     CellNumber NVARCHAR(20) NULL, 
     DriverTypeId INT NOT NULL, 
     ISDId INT NOT NULL, 
     CreatedBy NVARCHAR(50) NOT NULL, 
     DtCreated SMALLDATETIME NOT NULL, 
     LastUpdatedBy NVARCHAR(50) NOT NULL, 
     DtLastUpdated SMALLDATETIME NOT NULL, 
     PINCode NVARCHAR(20) NULL, 
     UNIQUE (DriverExternalId) 
    ) 

INSERT INTO @DriverToImport (DriverExternalId, DriverName, HireDate, HomeNumber, CellNumber, DriverTypeId, ISDId, CreatedBy, DtCreated, LastUpdatedBy, DtLastUpdated, PINCode) 
    SELECT 
     T.c.value('./Id[1]', 'NVARCHAR(20)'), 
     T.c.value('./Fn[1]', 'NVARCHAR(50)') + ', ' + T.c.value('./Ln[1]', 'NVARCHAR(50)') + ' ' + T.c.value('./Mn[1]', 'NVARCHAR(50)'), 
     T.c.value('./HireDate[1]', 'SMALLDATETIME'), 
     T.c.value('./HomeNumber[1]', 'NVARCHAR(20)'), 
     T.c.value('./CellNumber[1]', 'NVARCHAR(20)'), 
     (SELECT dt.DriverTypeId 
     FROM DriverType dt 
     WHERE dt.DriverTypeName LIKE '%' + T.c.value('./DriverType[1]', 'NVARCHAR(20)') + '%'), 
     @ISDId, @UserName, @dtCurrent, @UserName, @dtCurrent, 
     T.c.value('./PinCode[1]', 'NVARCHAR(20)') 
    FROM 
     @xmlDoc.nodes('/Drivers/Driver') T (c) 
    WHERE 
     (T.c.value('./Id[1]', 'NVARCHAR(20)') IS NOT NULL) 
     AND (T.c.value('./Id[1]', 'NVARCHAR(20)') <> '') 

DECLARE newDriverCursor CURSOR FAST_FORWARD FOR 
    SELECT 
     t.DriverExternalId, t.DriverName, t.HireDate, 
     t.HomeNumber, t.CellNumber, t.DriverTypeId, 
     t.CreatedBy, t.DtCreated, t.LastUpdatedBy, t.DtLastUpdated, 
     t.PINCode 
    FROM 
     @DriverToImport t 
    WHERE 
     (t.IsNew = 1) 

OPEN newDriverCursor 

FETCH NEXT FROM newDriverCursor INTO @DriverId, @DriverName, @HireDate, @HomeNumber, @CellNumber, @DriverTypeId, @CreatedBy, @DtCreated, @LastUpdatedBy, @DtLastUpdated, @PINCode 

WHILE (@@fetch_status = 0) 
BEGIN 
    INSERT INTO dbo.Driver (DriverExternalId, DriverName, EmployeeNumber, HireDate, HomeNumber, CellNumber, DriverTypeId, ISDId, CreatedBy, DtCreated, LastUpdatedBy, DtLastUpdated, PINCode, IsActive, ResetPIN) 
    VALUES (@DriverExternalId, @DriverName, @DriverExternalId, @HireDate, @HomeNumber, @CellNumber, @DriverTypeId, @ISDId, @CreatedBy, @DtCreated, @LastUpdatedBy, @DtLastUpdated, @PINCode, 1, 0) 
END 

我知道在过去,我已经使用了MERGE语句与SQL变量做批量插入不该做。哪一个工作得很好,但需要为每个表创建一个表变量。所以我的问题是在SQL Server 2016中有没有更强大的方式来处理批量插入?

+0

您应该使用CTE或合并语句。避免游标...即使有人持枪对你不使用游标:P –

+2

我没有在这里看到任何游标,顺便说一句,简单的INSERT INTO语句有什么问题? – FLICKER

+0

它只是省去了整个程序 - 更新包括更多的SPROC - 我同意我不喜欢使用它们,但为了做到这一点,我需要提出一个可行的替代方案 - 展望CTE – Jesse

回答

3

术语“批量插入”相当模糊,所以它的种类取决于您的意思。根据你的描述,这听起来像你可能想看SQL Server side.Net Framework side的表值参数。将XML字符串或分隔字符串直接传递给存储过程并在存储过程中进行XML分解的旧方法基本上是TVP打算取代的。从概念上讲,它所做的是允许您将.Net DataTable作为参数提交给存储过程。

但是,我也可以考虑批量插入的其他含义。有SqlBulkCopy class,它允许你作为一个单一的步骤相当有效地插入一个数据表。还有BULK INSERT SQL statement,主要用于加载CSV文件。此外,还有SSIS,这是一个完整的ETL包。如果您需要比BULK INSERT允许或需要执行额外映射更多的逻辑,则有些人已经使用SSIS在系统之间完成此操作。

所以,就像我说的,它的种类取决于“批量插入”的含义。

+0

这正是我需要的信息 - 谢谢:) – Jesse