且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-02-12 08:34:04

表定义是表定义 - 无论语法糖 ORM 工具可能覆盖.

Table definitions are table definitions - regardless of the syntactic sugar ORM tools might overlay.

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

I created a source and destination table and populated the source to match your supplied data. I do define the identity property on the destination table as well. Whether that's what a ValueGeneratedOnAdd is implemented as in the API, I don't know but it almost has to be otherwise the Enable Identity Insert should fail (if the UI even allows it).

IDENTITY 属性允许您使用您想要的任何初始值为其设定种子.对于目标表,我以有符号整数允许的最小值作为种子,这样如果身份插入不起作用,结果值看起来真的错误"

The IDENTITY property allows you to seed it with any initial value you want. For the taget table, I seed at the minimum value allowed for a signed integer so that if the identity insert doesn't work, the resulting values will look really "wrong"

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.源表创建时的标识为 1,但显式标识插入源表表将种子值提前到 32.假设没有其他活动发生,下一个值将是 33,因为我们的增量是 1.

Beyond your 3 supplied values, I added a fourth and if you run the supplied query, you'll see the generated ID is likely 33. Source table is created with an identity seeded at 1 but the explicit identity inserts on the source table advance the seed value to 32. Assuming no other activity occurs, next value would be 33 since our increment is 1.

说了这么多,我已经建立了 3 个场景.在导入导出向导中,我检查了 Identity Insert 并将 Id 映射到 ModuleCategoryId 并运行了包.

All that said, I have 3 scenarios established. In the Import Export wizard, I checked the Identity Insert and mapped Id to ModuleCategoryId and ran the package.

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

目标表中的数据与源表中的数据相同 - 正如预期的那样.此时,身份种子位于 33,我可以使用一些我不方便的 DBCC 检查命令进行验证.

The data in the target table is identical to the source - as expected. At this point, the identity seed is sitting at 33 which I could verify with some DBCC check command I don't have handy.

下一个案例是采用相同的包并取消选中 Identity Insert 属性.这将变得无效,因为我会收到错误报告

The next case is taking the same package and unchecking the Identity Insert property. This becomes invalid as I'd get an error reporting

插入只读列ModuleCategoryId"失败

Failure inserting into the read-only column "ModuleCategoryId"

唯一的选择是将 Id 取消映射到 ModuleCategoryId.假设我像以前一样加载到同一张表,我会看到类似这样的数据

The only option is to unmap the Id to ModuleCategoryId. Assuming I loaded to the same table as before, I would see data something like this

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

如果我从来没有将记录放入这个表中,那么我会得到这样的结果

If I had never put a record into this table, then I'd get results like

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

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

WITHOUT AN EXPLICIT ORDER BY ON MY SOURCE, THERE IS NO GUARANTEE OF RESULTS ORDERING. I fight this battle often. The SQL Engine has no obligation to return data in the primary key order or any other such order unless you explicitly ask for it. Had the following results been stored, it would be equally valid.

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

如果您有数据需要根据源表中Id的升序值插入到目标表中,在导入/导出向导中,您需要转到询问您是否要插入的屏幕选择表或编写查询并选择查询的第二个选项.然后,您将编写 SELECT * FROM dbo.SO_67370325_Source ORDER BY Id; 或任何源表的名称.

If you have a requirement for data to be inserted into the target table based on the ascending values of Id in the source table, in the Import/Export wizard, you need to go to the screen where it asks whether you want to pick tables or write a query and choose the second option of query. Then you will write SELECT * FROM dbo.SO_67370325_Source ORDER BY Id; or whatever your source table is named.

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

The final test, loading SO_67370325_Destination_noident, demonstrates a table with no identity property defined. If I do not map Id to ModuleCategoryId, the package will fail as the column is defined as NOT NULL. When I map the Id to ModuleCategoryId, I will see the same results as the first (7,14,32,33) BUT, every subsequent insert to the target table will have to provide their own Id which may or may not align with what your FluentAPI stuff does.

类似的问题/答案 错误 0xc0202049:数据流任务 1:插入只读列失败