【问题标题】:How to use BULK INSERT when rows depend on foreign keys values?当行依赖于外键值时如何使用 BULK INSERT?
【发布时间】:2011-12-05 03:09:31
【问题描述】:

我的问题与this one I asked on ServerFault有关。

基于此,我考虑过使用BULK INSERT。我现在明白我必须为要保存到数据库中的每个实体准备一个文件。无论如何,我仍然想知道这个 BULK INSERT 是否会避免我系统上的内存问题,如在 ServerFault 上引用的问题中所述。

至于 Streets 表,非常简单!作为外键,我只关心两个城市和五个部门。但是,地址呢? Addresses 表的结构如下:

AddressId int not null identity(1,1) primary key
StreetNumber int null
NumberSuffix_Value int not null DEFAULT 0
StreetId int null references Streets (StreetId)
CityId int not null references Cities (CityId)
SectorId int null references Sectors (SectorId)

正如我在 ServerFault 上所说,我有大约 35,000 个地址要插入。我要记住所有的ID吗? =P

然后,我现在要插入与地址有关联的公民。

PersonId int not null indentity(1,1) primary key
Surname nvarchar not null
FirstName nvarchar not null
IsActive bit
AddressId int null references Addresses (AddressId)

我唯一能想到的就是将 ID 强制为静态值,但是,我失去了以前使用 INSERT..SELECT 策略的方法所具有的任何灵活性。

那么我的选择是什么?

  1. 我强制 ID 始终相同,然后我必须 SET IDENTITY_INSERT ON 以便我可以将值强制到表中,这样我的每一行总是有相同的 ID,就像建议的那样here

  2. 如何使用外键批量插入?我在任何地方都找不到关于此的任何文档。 =(

感谢您的热心帮助!

编辑

我编辑是为了包含最终为我完成的BULK INSERT SQL 指令!

我已准备好 Excel 工作簿,其中包含我需要插入的信息。因此,我只是创建了一些补充工作表并开始编写公式,以便将信息数据“导入”到这些新工作表中。我的每个实体都有一个。

  1. 街道;
  2. 地址;
  3. 公民。

至于另外两个实体,不值得批量插入,因为我只有两个城市和五个部门(城市细分)要插入。插入城市和部门后,我记下它们各自的 ID 并开始准备我的记录集以进行批量插入。顺便说一句,使用 Excel 的强大功能来计算值并“导入”外键本身就是一种魅力。之后,我将每个工作表保存到单独的 CSV 文件中。然后我的记录就可以批量处理了。

USE [DatabaseName]
GO

delete from Citizens
delete from Addresses
delete from Streets

BULK INSERT Streets
    FROM N'C:\SomeFolder\SomeSubfolder\Streets.csv'
    WITH (
        FIRSTROW = 2
        , KEEPIDENTITY
        , FIELDTERMINATOR = N','
        , ROWTERMINATOR = N'\n'
        , CODEPAGE = N'ACP'
    )
GO
  • 第一次

    指示开始插入的行号。在我的情况下,我的 CSV 包含列标题,因此第二行是开始的行。另外,您可能希望从文件中的任何位置开始,比如第 15 行。

  • 保持身份

    即使表具有标识列,也允许批量插入指定的文件内实体 ID。当您希望使用精确的 id 插入时,此参数与插入行之前的 SET INDENTITY_INSERT my_table ON 相同。

至于其他参数,他们自己说话。

现在已经解释了这一点,为其余两个实体中的每一个重复相同的代码以插入地址和公民。而且因为指定了KEEPIDENTITY,所以我的所有外键都保持不变,尽管我的主键在 SQL Server 中设置为标识。

不过,只有一些调整,与marc_s 在他的回答中所说的完全相同,只需尽可能快地将数据导入暂存表,完全没有任何限制。这样,您将使您的生活更轻松,同时遵循良好的做法。 =)

【问题讨论】:

    标签: tsql memory foreign-keys bulkinsert


    【解决方案1】:

    基本思想是将您的数据批量插入到一个没有任何限制、任何约束等的暂存表中 - 尽可能快地批量加载数据。

    一旦您在临时表中获得数据,那么当您将临时表中的数据插入到真实表中时,您需要开始担心约束等问题。

    在这里,你可以例如

    • 仅将那些符合所有条件的行插入到实际工作表中(并在临时表中将它们标记为“成功插入”)

    • 处理暂存表中未通过某些错误/恢复过程成功插入的所有行 - 无论是什么:打印包含所有“问题”行的报告,将它们扔进“错误箱”或其他任何东西 - 完全取决于您。

    关键点是:实际的BULK INSERT 应该在一个完全不受约束的表中 - 尽可能快地加载数据 - 然后在第二步开始担心约束和查找数据和引用之类的东西那个

    【讨论】:

    • 我们的应用使用这种精确的策略一次加载数百万行。
    • 这是有道理的,毕竟。一旦插入数据行,它们总是更容易操作。谢谢你的一粒盐,马克! =)
    • 我终于成功批量插入了数千行!至于外键,有一个特殊的参数KEEPIDENTITY,所以可以在他的CSV文件中指定外键值,并期望插入这些外键值。
    猜你喜欢
    • 2013-03-13
    • 2017-07-15
    • 1970-01-01
    • 2020-11-14
    • 1970-01-01
    • 2019-02-11
    • 2019-08-30
    • 2011-04-09
    • 1970-01-01
    相关资源
    最近更新 更多