【问题标题】:Bulk Inserts SQL Server批量插入 SQL Server
【发布时间】:2016-12-16 21:08:00
【问题描述】:

我很好奇是否有人可以提出更好的批量插入方法。在我目前的工作中,我们正在构建作为变量传递给存储过程的 xml 字符串,然后创建一个临时表并插入 xml。很多时候我看到使用了一个光标,如果可能的话我不想这样做

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 变量的合并语句来进行批量插入。这也很好用,但需要为每个变量创建一个表变量。所以我的问题是在 SQL Server 2016 中是否有更强大的方法来处理批量插入?

【问题讨论】:

  • 您应该使用 CTE 或合并语句。避免使用光标……即使有人拿着枪对着你,也不要使用光标:P
  • 我没有看到任何光标,顺便说一句,简单的 INSERT INTO 语句有什么问题?
  • 我只是省去了整个过程 - 更新为包含更多的 SPROC - 我同意我也不喜欢使用它们,但为了做到这一点,我需要提供一个可行的替代方案- 调查 CTE
  • 简单的插入语句不起作用的原因是,在某些过程中,我们会为每个行更新/插入尝试提供详细的反馈。因此,在这些情况下,逻辑将应用于每个通道以更新临时日志表。在这些情况下,我不知道如何避免使用游标 - SQL 不是我的强项:(

标签: sql-server bulkinsert


【解决方案1】:

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

不过,我也能想到批量插入的其他含义。有SqlBulkCopy class,它允许您以一个步骤相当有效地插入数据表。还有BULK INSERT SQL statement,主要用于加载CSV 文件。此外,还有 SSIS,它是一个完整的 ETL 包。如果您需要的逻辑多于 BULK INSERT 所允许的或需要进行额外的映射,有些人已经使用 SSIS 在系统之间完成此任务。

所以,就像我说的,这有点取决于您所说的“批量插入”。

【讨论】:

  • 这正是我需要的信息 - 谢谢 :)
猜你喜欢
  • 2010-09-24
  • 1970-01-01
  • 2021-06-05
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多