【问题标题】:How to make bulk insert work with multiple tables如何使批量插入适用于多个表
【发布时间】:2011-11-15 04:26:22
【问题描述】:

当存在外键关系时,如何使用 SQL Server 批量插入插入多个表?

我的意思是桌子是这样的,

CREATE TABLE [dbo].[UndergroundFacilityShape]
([FacilityID] [int] IDENTITY(1,1) NOT NULL,
[FacilityTypeID] [int] NOT NULL,
[FacilitySpatialData] [geometry] NOT NULL)

CREATE TABLE [dbo].[UndergroundFacilityDetail]
([FacilityDetailID] [int] IDENTITY(1,1) NOT NULL,
[FacilityID] [int] NOT NULL,
[Name] [nvarchar](50) NOT NULL,
[Value] [nvarchar](255) NOT NULL)

所以每个 UndergroundFacilityShape 可以有多个 UndergroundFacilityDetail。问题是在插入完成之前没有定义 FacilityID,因为它是一个标识列。如果我将数据批量插入到 Shape 表中,那么我无法将其与我在 C# 应用程序中的详细信息数据进行匹配。

我猜解决方案是运行一条 SQL 语句来找出下一个标识值是什么并自己填充这些值并关闭批量插入的标识列?请记住,只有一个人会运行此应用程序来插入数据,并且不会经常执行此操作,因此我们不必担心身份值冲突或类似的事情。

我正在尝试导入数千条记录,使用标准插入大约需要 3 分钟,但批量插入需要几秒钟。

未来我希望导入比“数千”条记录大得多的数据。

【问题讨论】:

  • 您是否考虑过使用 SSIS 代替 BULK INSERT?
  • 批量插入用于正确构建的数据。如果您在插入时有未知关系(例如您的父/子外键值),则不适合批量插入。
  • 我目前有一个使用直插的解决方案,因此任何解决方案都必须比这更快。这就是我的目标。否则我就让它保持原样。
  • 如果您在插入前后禁用/启用身份会怎样?
  • 文件结构是什么?你也可以展示你的插入解决方案,也许我们可以加快速度。

标签: sql sql-server-2008


【解决方案1】:

事实证明这很简单。获取每个表上的当前标识值,并将它们填充到 DataTable 中,并在我使用它们时自行递增它们。我还必须确保使用正确的值来维持关系。而已。我是否关闭身份列似乎并不重要。

我在实时数据上使用这个工具已经有一段时间了,效果很好。

虽然导入时间不超过 3 秒(而不是 3 分钟),但还是值得的,而且我希望在某个时候收到更大的数据集。

那么,如果不止一个人同时使用该工具怎么办?嗯,是的,我预计会出现问题,但对我们来说永远不会是这样。

【讨论】:

  • 那么从您获取分配给头表的最后一个Id到您完成更新的时间,没有其他进程将记录插入到头表中?如果您不能保证这一点,您可能会发生密钥冲突。
  • 正如 Eric J 所暗示的那样,你有自己的比赛条件。
【解决方案2】:

彼得,你提到你已经有了直接INSERTs 的解决方案。

如果目标表没有聚集索引(或有聚集索引但为空),只需使用TABLOCK 查询提示将使其成为最少记录的事务,从而显着提高速度。

如果目标表具有聚集索引且不为空,则除了TABLOCK 查询提示之外,您还可以启用跟踪标志 610 以使其成为最少记录的事务。

检查INSERT MSDN page 上的“使用INSERT INTO…SELECT 以最少的日志记录批量导入数据”部分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-19
    • 1970-01-01
    相关资源
    最近更新 更多