65.9K
CodeProject 正在变化。 阅读更多。
Home

数据库重置器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.36/5 (9投票s)

2004年10月3日

4分钟阅读

viewsIcon

123742

downloadIcon

634

一个让数据库开发生活更轻松的小工具。

Sample Image - Database_Resetter.gif

引言

本文介绍了一个小型实用工具,可用于将数据库重置为干净状态。在开发使用数据库的应用程序时,这可能需要相当频繁。

这个实用工具是快速构建的,因此不会获得任何风格奖项,但它对我来说确实有效!

背景

这个实用工具的灵感源于纯粹的沮丧。在许多项目中,我们都在处理一个数据库,该数据库的结构和默认数据都经常更改。这些更改大多很小,但由于这些微小的更改,保持高效的工作流程变得越来越困难。结构和默认数据的更改必须在两个地方进行。还需要导入测试数据或实际数据。所有这些都为小的(以及大的)错误敞开了大门。

这个实用工具——它本应该在一年前就写好——依赖于数据库的某些特性来删除其中的所有非默认数据,并清理自动编号(或标识)值,以便可以愉快地插入新数据,而不会出现讨厌的 ID 间隙。

使用代码

执行所有工作的代码包含在一个单独的库中,因此可以被不同的项目重用。有一个独立的应用程序,可以在几秒钟内重置数据库。该库也可以包含在一个导入工具中,使该工具能够在导入数据之前重置数据库。

这个实用工具的基本思想是将所有默认数据标记为默认数据,然后删除任何未标记的数据。为了标记默认数据,在包含默认数据的表中添加了一个特定的列。在示例项目中,此列称为 IsStatic。它的类型是 bit,如果记录应被保留,其值应为 1。任何 IsStatic 设置为 0 的记录都将被删除。任何不包含 IsStatic 列的表都将被完全清空。

该库可以通过两种方式使用。它可以用于批量擦除数据库,也可以用于按表为单位擦除数据库。后者允许提供进度反馈。

要使用该代码,只需实例化该类,提供连接字符串和要测试的列名。使用 ResetAllTables 函数可以实现对整个数据库的批量擦除。

Dim resetter As PhoenixConsultancy.Utilities.Database.Reset = _
    New PhoenixConsultancy.Utilities.Database.Reset

resetter.StaticColumnName = "IsStatic"
resetter.ConnectionString = connectionString

resetter.Initialize()
resetter.ResetAllTables()
TextBoxResults.Text &= "Bulk reset completed." & vbCrLf
resetter.DeInitialize()

为了逐个重置表,可以获取一个表列表并进行循环。表列表还包含有关已删除记录数量以及表是否已重置的信息。在批量重置后也可以获得此列表,以便提供状态信息。

Dim resetter As PhoenixConsultancy.Utilities.Database.Reset = _
    New PhoenixConsultancy.Utilities.Database.Reset
Dim tables As PhoenixConsultancy.Utilities.Database.TableInfo()
Dim table As PhoenixConsultancy.Utilities.Database.TableInfo

resetter.StaticColumnName = "IsStatic"
resetter.ConnectionString = connectionString

resetter.Initialize()
tables = resetter.Tables
For Each table In tables
    If table.ResetDone Then
    TextBoxResults.Text &= "Table " & table.Name & _
        " was already reset, " & table.RecordsDeleted & _
        " records were deleted" & vbCrLf
    Else
    resetter.ResetTable(table)
    If table.ResetDone Then
    TextBoxResults.Text &= "Table " & table.Name & _
        " has been reset, " & table.RecordsDeleted & _
        " records were deleted" & vbCrLf
    Else
    TextBoxResults.Text &= "Table " & table.Name & _
        " has *not* been reset, " & table.RecordsDeleted & _
        " records were deleted" & vbCrLf
    End If
    End If
Next
resetter.DeInitialize()

可下载的 zip 文件包含库的源代码和二进制文件以及一个演示应用程序。使用此实用工具时要小心。在测试之前备份您的数据库!如果您不确定此实用工具的作用,请查看源代码!

关注点

需要解决的两个主要问题是表之间的依赖关系和重置标识值。

为了解决依赖问题,我利用了 SQL Server 中的系统表。使用这些表,我可以(一旦你知道方法,就相当简单地)找出哪个表依赖于哪个其他表。使用递归函数,我遍历依赖关系树,并首先重置没有依赖关系的表。在重置表之后,会设置一个标志,以便同一表不会被再次重置。用于查找相关表的查询如下所示:

SELECT  sysobjects.name AS RelatedTable
FROM    sysobjects
INNER JOIN  syscolumns ON sysobjects.id = syscolumns.id
INNER JOIN  sysforeignkeys ON syscolumns.id = sysforeignkeys.fkeyid
   AND  syscolumns.colid = sysforeignkeys.fkey
INNER JOIN  syscolumns syscolumns2 
   ON sysforeignkeys.rkeyid = syscolumns2.id
   AND  sysforeignkeys.rkey = syscolumns2.colid
INNER JOIN  sysobjects sysobjects2 ON syscolumns2.id = sysobjects2.id
WHERE   sysobjects2.name = 'TableName'

重置标识值(同样,一旦你知道方法)一点也不难。根据 Microsoft 的文档,有两种方法可以做到这一点。我选择了 SQL Server 自行计算的方法。首先,我将标识重置为可能的最小值。如果表中包含数据并且您尝试执行 insert,这将会导致错误。

DBCC CHECKIDENT('TableName', RESEED, 0)

为了再次理顺一切,我发出了一个参数少一个的相同查询。现在 SQL Server 会计算当前使用的最高 ID 是多少,并相应地调整标识值。结果是一个表,其中新的 insert 会按顺序排列。

DBCC CHECKIDENT('TableName', RESEED)

历史

我发现并修复了一个关于重置标识的小问题。当我最初将新种子设置为 1 时,任何新的插入都将从 ID 2 开始。当表完全为空时,这会很麻烦。它甚至可能破坏依赖于 ID 1 存在的代码。

除上述内容外,还没有太多历史记录。不过还有一些工作要做。我希望添加的一些功能包括:

  • 用于生产/部署数据库的 IsStatic 列移除器
  • IsStatic 列添加工具,以便更容易地将该实用工具应用于尚未准备好的数据库。

这些功能并不难实现,但时间宝贵……

© . All rights reserved.