0

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

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

换句话说...

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

我们已经“丢失”了 100 条记录的范围。是否存在与自动增量相同的“自动减量”?

4

4 回答 4

3

自动编号对您来说不应该那么有意义。他们的保证是他们只提供唯一性。如果您使用的是 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  
于 2012-05-11T20:25:47.263 回答
2

删除时自动递减听起来是个坏主意。如果操作不正确,您可以开始在代码中注入更大的错误。如果 ID 很重要,请尝试给它一个批号,并为批次中的每个项目提供一个递增的 ID。您也可以使用指南,尽管它们不是顺序的。

于 2012-05-11T20:27:08.570 回答
2

您可以通过执行以下操作重新设置 AutoIncrement ID:

DBCC CHECKIDENT
(
  tablename

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

但是,我不建议将此作为最佳实践。您的查询应该是原子的(如果失败,它会提交并更新表或回滚(保持 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

于 2012-05-11T20:27:32.233 回答
0

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

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

于 2012-05-12T17:31:39.497 回答