SSIS - 自动增量字段未正确插入数据流任务

SSIS - Auto increment field is not inserted correctly with data flow task

我正在尝试使用 ssis 将数据从一个数据库复制到另一个数据库。我使用 SQL 服务器导入和导出向导创建了 dtsx 包。 我从中复制的 table 有一个列名“Id”,另一个 table 有一个名称“ModuleCategoryId”,我将它们映射在一起。

ModuleCategoryId 是标识,自动递增 1。 在源数据库中,Id 没有排序,并且是这样的:

执行数据流后,目标数据库如下所示:

我在向导中启用了标识插入,但这没有任何作用。

目标数据库是使用 Entity Framework 创建的,代码优先。

如果我明确关闭 ValueGeneratedOnAdd,并重新制作目标数据库,数据将被正确传输,但我想知道是否有一种方法可以在不关闭自动增量的情况下传输所有数据,然后再将其返回上。

如果我为那个 table 手动设置标识插入,我可以使用我想要的任何 ModuleCategoryId 插入行,所以它必须与数据流有关。

Table 定义是 table 定义 - 不管语法糖 ORM 工具可能覆盖。

我创建了源和目标 table 并填充了源以匹配您提供的数据。我也在目标 table 上定义了身份 属性。这是否是 ValueGeneratedOnAdd 在 API 中实现的,我不知道,但它几乎必须是,否则启用身份插入应该失败(如果 UI 甚至允许它) .

IDENTITY 属性 允许您使用您想要的任何初始值作为种子。对于 taget table,我以有符号整数允许的最小值作为种子,这样如果身份插入不起作用,结果值看起来真的“错误”

DROP TABLE IF EXISTS dbo.SO_67370325_Source;
DROP TABLE IF EXISTS dbo.SO_67370325_Destination;

CREATE TABLE dbo.SO_67370325_Source
(
    Id int IDENTITY(1,1) NOT NULL
,   Name varchar(50)
);
CREATE TABLE dbo.SO_67370325_Destination
(
    ModuleCategoryId int IDENTITY(-2147483648,1) NOT NULL
,   Name varchar(50)
);

CREATE TABLE dbo.SO_67370325_Destination_noident
(
    ModuleCategoryId int NOT NULL
,   Name varchar(50)
);

SET IDENTITY_INSERT dbo.SO_67370325_Source ON;
INSERT INTO DBO.SO_67370325_Source
(
    Id
,   Name
)
VALUES
    (32, 'Name1')
,   (14, 'Name2')
,   (7, 'Name3');
SET IDENTITY_INSERT dbo.SO_67370325_Source OFF;

INSERT INTO dbo.SO_67370325_Source
(
    Name
)
OUTPUT Inserted.*
VALUES
(
    'Inserted naturally' -- Name - varchar(50)
);

除了你提供的 3 个值,我添加了第四个,如果你 运行 提供的查询,你会看到生成的 ID 可能是 33。源 table 是用身份种子创建的在 1 但显式身份插入源 table 将种子值提高到 32。假设没有其他 activity 发生,下一个值将是 33,因为我们的增量是 1.

综上所述,我已经建立了 3 个场景。在 Import Export 向导中,我检查了 Identity Insert 并将 Id 映射到 ModuleCategoryId 和 运行 包。

ModuleCategoryId|Name
32|Name1
14|Name2
7|Name3
33|Inserted naturally

目标 table 中的数据与源中的数据相同 - 正如预期的那样。此时,身份种子位于 33,我可以使用一些我手边没有的 DBCC 检查命令来验证它。

下一个案例是采用相同的包并取消选中标识插入 属性。这变得无效,因为我会收到错误报告

Failure inserting into the read-only column "ModuleCategoryId"

唯一的选择是取消 Id 到 ModuleCategoryId 的映射。假设我加载到与以前相同的 table,我会看到类似这样的数据

ModuleCategoryId|Name
34|Name1
35|Name2
36|Name3
37|Inserted naturally

如果我从来没有将记录放入此 table,那么我会得到类似

的结果
ModuleCategoryId|Name
-2147483648|Name1
-2147483647|Name2
-2147483646|Name3
-2147483645|Inserted naturally

如果没有在我的来源上明确订购,则无法保证订购结果。我经常打这场仗。 SQL 引擎没有义务 return 主键顺序或任何其他此类顺序中的数据,除非您 明确地 要求它。如果存储了以下结果,则同样有效。

ModuleCategoryId|Name
34|Inserted naturally
35|Name1
36|Name2
37|Name3

如果您需要根据源 table 中 Id 的升序值将数据插入目标 table,在 Import/Export 向导中,您需要转到询问您是要选择 tables 还是编写查询的屏幕,然后选择查询的第二个选项。然后你会写 SELECT * FROM dbo.SO_67370325_Source ORDER BY Id; 或任何你的来源 table 被命名。

最后的测试,加载 SO_67370325_Destination_noident,演示了一个没有定义身份 属性 的 table。如果我不将 Id 映射到 ModuleCategoryId,则包将失败,因为该列被定义为 NOT NULL。当我将 Id 映射到 ModuleCategoryId 时,我会看到与第一个 (7,14,32,33) 相同的结果,但是,每个后续插入目标 table 都必须提供自己的 Id,这可能会或可能与您的 FluentAPI 内容不一致。

相似question/answerError 0xc0202049: Data Flow Task 1: Failure inserting into the read-only column