2016-12-16 8 views
0

誰かが一括挿入を行うより良い方法を提案できるかどうか不思議です。私の現在の仕事では、変数としてストアドプロシージャに渡されたxml文字列を作成してから、テンポラリテーブルを作成してxmlを挿入しています。多くの時間は、私は過去に、私は一括挿入を行うためにSQL変数とマージステートメントを使用していた知っている可能Bulk Inserts 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 

場合、私はやっていないことを好む使用されているカーソルを参照してください。どちらもうまくいくが、それぞれにテーブル変数を作成する必要がある。だから私の質問は、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があり、DataTableをかなり効率的に1つのステップとして挿入することができます。 BULK INSERT SQL statementもあります。これは、主にCSVファイルの読み込みを目的としています。さらに、完全なETLパッケージであるSSISもあります。 BULK INSERTよりも多くのロジックが必要な場合や、追加マッピングを行う必要がある場合は、SSISを使用してシステム間でそれを実現するものがあります。

だから、私が言ったように、それはあなたが「一括挿入」を意味するかどうかにかかっています。

+0

これは私が必要とした情報です - ありがとう:) – Jesse