删除记录时自动减少T-SQL ID?

时间:2012-05-11 20:22:56

标签: sql sql-server tsql

在我们的某个应用中,我们从文件中读取数据并将其扩展为多个表格。如果文件的任何部分损坏,我们将暂停读取,并删除插入的任何数据。

这里的问题是我们在其中一个导入表上有一个自动增量ID,当我们删除一个问题文件时,ID会从其导入后的值继续,而不是它的导入前值。

换句话说......

  • ID从50开始。
  • 插入100条记录,最大ID现在为150.
  • 删除100条记录,最大ID仍为150.
  • 插入50条记录,ID为200.

我们“丢失”了100条记录的范围。是否有“自动减量”等同于自动增量?

4 个答案:

答案 0 :(得分:3)

Autonumbers对你来说不应该那么有意义。他们的保证是他们不再提供独特性。如果您使用的是SQL Server DBCC CHECKIDENT,则仍可以重新设置。

Checks the current identity value for the specified table and, if it is needed, changes the identity value. You can also use DBCC CHECKIDENT to manually set a new seed value for the identity column.

来自BOL: 以下示例将AdventureWorks数据库中Employee表中的当前标识值强制为值30。

USE AdventureWorks;
GO
DBCC CHECKIDENT ('HumanResources.Employee', RESEED, 30);
GO

我不是推荐这个,而是指出来。如果您尝试重新设定已经使用的值,DBCC CHECKIDENT会抛出错误,在这种情况下,如果您依赖此类任务,则必须具有逻辑。

我质疑这些数字如此重要的思维过程?听起来你想要一个名为LineNumber的额外字段增加或减少等等。但即使在这种情况下你也必须处理删除记录之后的行。因此,如果您有50行并删除第25行,则必须重新编号大于25的行:

UPDATE 
       MyTable 
SET LineItemNumber = LineItemNumber - 1 
WHERE 
       LineItemNumber > @LineItemNumberToBeDeleted  

答案 1 :(得分:2)

删除时自动减少听起来像个坏主意。如果操作不正确,您可以开始在代码中注入更大的错误。如果ID是一个大问题,请尝试给它一个批号,并为批处理中的每个项目增加一个id。你也可以使用guids,虽然它们不是连续的。

答案 2 :(得分:2)

您可以通过执行以下操作重新设置自动增量ID:

DBCC CHECKIDENT
(
  tablename

  [, [NORESEED | RESEED [, newreseedvalue]]]
)

但我不建议将此作为最佳做法。您的查询应该是原子的(它提交并更新表或者如果失败则返回Rollsback(保持ID不变)。要实现原子查询,您可以使用TRANSACTION

BEGIN TRY
   BEGIN TRANSACTION @TranName;

     -- Your database logic here

    COMMIT TRANSACTION @TranName;

END TRY

BEGIN CATCH

   ROLLBACK TRAN @TranName;

END CATCH

GO

来源:

http://msdn.microsoft.com/en-us/library/ms188929.aspx

http://www.techrepublic.com/blog/datacenter/how-do-i-reseed-a-sql-server-identity-column/406

答案 3 :(得分:0)

根据我的经验,这部分ETL(提取变换加载)过程的最佳实践是在多个步骤中执行批量加载:

  1. 将文件中的数据加载到仅用于此目的的空“加载”或“分段”表中。这会检测文件级损坏。
  2. 检查数据的参照完整性和其他验证。这会检测数据级错误。
  3. 仅将有效数据插入“真实”表格。这样可以避免不必要的删除并避免浪费自动增量值。
  4. 记录或报告导入检查失败的数据。
  5. 在下一次执行此过程之前,请截断“加载”表。