0

**更新(2017 年 5 月 18 日)**

我发现问题并没有我想象的那么大。这仅在部署模式后发生,并且在初始阶段迁移错误。唯一需要部署模式的情况是新数据库是否有新的或修改。然后,一旦迁移工具开始,它必须成功填充整个数据库(大约需要 20 分钟),因此错误数 * 完成所需的时间 = 修复所有错误的总时间,这可能需要几个小时。但是,如果这种情况发生,那就有点令人不安了。如果迁移成功,并且没有对架构进行任何修改,那么下面的场景就不会麻烦了。这些修改不会经常发生,可能每月一次或两次。不过,我仍然对其他类型的解决方案感兴趣。

**原始帖子(2017 年 5 月 17 日)**

我已经查看了以下相关的 Stack Overflow 问题,但没有人回答我正在经历的问题。

为什么在 SQL Server 2008 R2 中设置当前标识值对我不起作用?

无法截断表,因为它被 FOREIGN KEY 约束引用?

背景故事

我的任务是迁移数据库,涉及表的重组,确保它具有数据完整性,并简化架构。本次迁移由c#应用程序执行,调用存储过程,添加业务逻辑等。每天早上5点,有一个任务调度器清空除审计表之外的所有数据,并取回所有刷新的数据(如果原数据已更新)。迁移工具是幂等的,这样可以删除和重新创建数据库,运行迁移工具后一切恢复正常(有刷新数据)。此外,迁移工具首先通过引用表导入相关数据,以确保不会发生违反约束的情况,并且它还会选择那些索引 ID,而不是任何旧的遗留 ID。每个表也有 IDENTITY (1,1)

为了确保刷新数据库,我必须执行 DELETE FROM 操作。截断表不起作用,因为会违反外键约束。所以我这样做的方式是关闭约束,从数据中删除,重新打开约束,然后重新设置值。

所以当我的程序运行时,它会执行以下几行:

sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
sp_MSForEachTable 'DELETE FROM ?'
EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'"
EXEC sp_MSforeachtable 'DBCC CHECKIDENT(''?'', RESEED, 0)'

但是,如果数据库实例是全新安装的,并且我运行迁移工具并出现错误,则会出现问题,因为某些表不会被填充。由于少数表插入了记录,而其他表没有插入记录;这意味着,如果我在迁移工具中再次运行上述代码,插入记录的表的下一个种子值将是 ID=1,而未触及表的种子值将为空(并且第一个插入将从 ID=0 开始)。这是因为这会覆盖 IDENTITY (1,1)。如果我要在没有插入记录的表上运行 DBCC CHECKIDENT,例如

DBCC CHECKIDENT ('TABLEA', NORESEED)

您会得到以下信息:

检查身份信息:当前身份值“NULL”,当前列值“NULL”。

无论您做什么,都不能将身份值“NULL”重新设置为任何其他数字。

这成为一个严重的问题,因为每次迁移工具运行时,我都会遇到外键约束违规,因为引用的表中不存在某些索引。这也有一个多米诺骨牌效应,如果一个表的索引不正确(ID = 0),所有引用该表的表都将违反约束 - 跳过导入,并且这些表上的索引将是 ID = 0 以及下一个我们运行迁移工具的时间。

HACK 解决方案:

我希望所有表都从 ID=1 开始,而不是 0。所以到目前为止,确保它运行的唯一可能方法是从干净的状态中清除数据库(删除并重新创建),评论去掉上面的四个命令代码,运行迁移工具,希望填充所有表成功,回到代码,取消注释四个命令代码,将工具部署到任务调度器中。

问题

有什么方法DBCC CHECKIDENT可以返回我的 c# 应用程序可以识别的值,或者可能找到/忽略所有尚未插入的表,以便我只能重新设置已插入的表?或者我应该尝试跟踪运行了哪些表,并查看迁移工具是否可以在下次运行时忽略这些表?如果是这种情况,那么最好的方法是什么?

4

0 回答 0