2016-12-16 194 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