【问题标题】:How should I approach migrating data from a "bad" database design to a usable design?我应该如何将数据从“糟糕”的数据库设计迁移到可用的设计?
【发布时间】:2010-10-14 18:33:09
【问题描述】:

我继承的当前项目主要围绕一个未规范化的表。有一些标准化的尝试,但没有设置必要的限制。

示例:在 Project 表中,有一个客户名称(以及其他值),还有一个仅包含客户名称的客户表 [任何地方都没有键]。客户表仅用作在添加新项目时为用户提供的值池。客户表上没有主键或外键。

诸如此类的“设计模式”在数据库的当前状态和使用它的应用程序中很常见。我可以使用的工具是 SQL Server 2005、SQL Server Management Studio 和 Visual Studio 2008。我最初的方法是手动确定哪些信息需要规范化并运行 Select INTO 查询。有没有比逐个案例更好的方法,或者无论如何这可以自动化?

编辑: 此外,我发现“工作订单号”不是 IDENTITY(自动编号,唯一)字段,它们是按顺序生成的,并且对于每个工作订单都是唯一的。现有编号中也有一些空白,但都是独一无二的。编写存储过程以在迁移之前生成虚拟行的最佳方法是什么?

【问题讨论】:

  • 你是这个项目的唯一开发者,还是你必须担心破坏其他开发者和客户访问的东西?
  • 我是唯一的开发者。这家公司没有任何认真的开发人员(仅我的部门每年就有 1000 万)。只有从事此工作的人可能甚至不知道 RDBMS 是什么。

标签: sql sql-server refactoring rdbms normalization


【解决方案1】:

迁移到可用设计的最佳方法是什么? 小心

除非您愿意破坏(并修复)当前使用数据库的每个应用程序,否则您的选择是有限的,因为您无法对现有结构进行太多更改。

在开始之前,请仔细考虑您的动机 - 如果您有一个现有问题(要修复的错误,要进行的增强),那么请慢慢进行。然而,为了获得别人不会注意到的改进而在工作的生产系统上胡闹是不值得的。请注意,这可能对您有利 - 如果存在现有问题,您可以向管理层指出解决问题的最具成本效益的方法是以 this 方式更改数据库结构。这意味着您对更改有管理支持 - 并且(希望)如果事情变成梨形,他们的支持。

一些实际的想法...

一次进行一项更改 ...并且一项更改。在继续之前,请确保每个更改都是正确的。 “量两次,切一次”这句老话很贴切。

自动化 自动化 自动化 ...永远不要使用 SQL Server Management Studio 对生产系统进行“实时”更改。编写一次性执行整个更改的 SQL 脚本;针对数据库的副本进行开发和测试,以确保您得到正确的结果。不要将生产环境用作测试服务器——你可能会不小心对生产环境运行脚本;使用专用的测试服务器(如果数据库大小在 4G 以下,请使用在您自己的机器上运行的 SQL Server Express)。

备份 ...任何脚本的第一步都应该是备份数据库,以便在出现问题时有办法返回。

文档 ...如果有人在 12 个月后来找您,询问他们应用程序的功能 X 为何损坏,您将需要确切更改的历史记录制成数据库,以帮助诊断和修复。第一步是保留所有更改脚本。

...在数据库中保持主键和外键抽象而不通过应用程序显示通常是一个好主意。在业务层面看起来像钥匙的东西(比如您的工作订单号)有一个令人不安的习惯,即出现异常。将您的键作为具有适当约束的附加列引入,但不要更改现有键的定义。

祝你好运!

【讨论】:

  • 废话!我打算提供大约一半的建议。我什至没有想到另一半!
【解决方案2】:
  1. 按照您认为的结构方式创建新数据库。
  2. 在新数据库中创建一个 importError 表,其中包含“oldId”和“errorDesc”等列
  3. 编写一个简单、程序化、易读的脚本,尝试从旧结构中选择一行并将其插入到新结构中。如果插入失败,请在 importError 表中记录尽可能具体的错误(具体来说,为什么插入失败)。
  4. 运行脚本。
  5. 验证新数据。检查是否有错误记录到 importError 表中。如果数据无效或有错误,请重构您的脚本并再次运行它,可能在必要时修改您的新数据库结构。
  6. 重复步骤 1-5,直到获得可靠的转换脚本。

此过程的结果将是您拥有: a) 一个新的数据库结构,它针对旧结构进行了验证,并针对“实用主义”进行了测试; b) 您可能需要编写代码的潜在问题的日志(例如您无法通过转换修复的错误,因为它们需要您不想要的架构中的让步)

(我可能会注意到,使用您选择的脚本/编程语言而不是 SQL 来编写脚本会很有帮助。)

【讨论】:

    【解决方案3】:

    我想不出一种明智的方式来实现自动化......如果您希望输出有用的话,一些人工输入是此类重构的关键。

    重新工作订单号;假设您希望它继续作为 IDENTITY 列;您能否填充数据,找到最大的,然后使用 ALTER TABLE 使其成为 IDENTITY?我手头没有任何 TSQL 工具,所以很遗憾,我无法测试。或者,只需将其视为 自然键

    【讨论】:

      【解决方案4】:

      我建议使用存储过程来帮助翻译过程。

      具体来说:

      1. 一一将代码中使用的查询替换为存储过程。作为替换的一部分,直接针对存储过程编写单元(或集成)测试。考虑使用代码级 StoredProcs 帮助类来整合那里的数据库访问。
      2. 在所有查询都是存储过程之后,您可以重构数据库,使用这些单元测试来确保您没有改变预期的行为。
      3. 附加优势:您将拥有这些单元测试以防止未来出现问题。

      【讨论】:

        【解决方案5】:

        您没有说是否需要保留当前的应用程序界面,或者您是否打算重写应用程序中的任何查询。

        无论如何,我都会

        • 设计新架构
        • 编写 T-SQL 批处理,在必要时使用游标来迁移数据

        游标虽然不是操作查询的首选,但非常适合此类应用程序,因为您可以以非常结构化的方式执行任务。这些脚本的可读性很强,当它不能立即工作并且您已经经历了几次迭代时,这一点很重要。

        【讨论】:

          【解决方案6】:

          您可以使用作为 SQL Server 2005 一部分的 SQL Server Integration Services (SSIS) 来帮助您进行迁移。它用于将数据从一种形式传输到另一种形式:

          http://en.wikipedia.org/wiki/SQL_Server_Integration_Services http://www.microsoft.com/sqlserver/2005/en/us/integration-services.aspx

          【讨论】:

            【解决方案7】:

            只是添加一个简单的提示。当您将实体关系图放在面前的一张 A4 或 A3 上时,适当的规范化将意味着没有多对多的关系。 也检查这个book or at least the site

            【讨论】:

              猜你喜欢
              • 2010-09-15
              • 2021-10-02
              • 2012-04-23
              • 2015-04-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-03-16
              • 1970-01-01
              相关资源
              最近更新 更多