SQL Server 2005 : Wrapping Tables by Views - Pros and Cons

标签 sql sql-server database refactoring

背景
我正在开发一个遗留的小型企业自动化系统(库存、销售、采购等),该系统具有由 SQL Server 2005 和一堆客户端应用程序托管的单个数据库。主要客户端(供所有用户使用)是 MS Access 2003 应用程序 (ADP),其他客户端包括各种 VB/VBA 应用程序,如 Excel 插件和命令行实用程序。
除了 60 个左右的表(大部分在 3NF 中)之外,该数据库还包含大约 200 个 View 、大约 170 个 UDF(主要是标量和表值内联的)和大约 50 个存储过程。正如您可能已经猜到的那样,所谓的“业务逻辑”的某些部分被封装在大量的 T-SQL 代码中(因此由所有客户端共享)。
总的来说,系统的代码(包括 T-SQL 代码)组织得不是很好,可以说是非常抗重构的。特别是,大多数表的模式都需要各种重构,小(如列重命名)和大(如规范化)。
FWIW,我有相当长且不错的应用程序开发经验(C/C++、Java、VB 等等),但我不是 DBA。所以,如果这个问题对你来说看起来很傻,现在你知道为什么会这样了。 :-)

在考虑重构所有这些烂摊子时(当然是以和平方式),我想出了以下想法:

  • 对于每个表,创建一个“包装器” View ,其中 (a) 具有该表具有的所有列; (b) 在某些情况下,基于表的“真实”列有一些额外的计算列。
    这种附加计算列的典型(尽管很简单)示例是从产品的正常价格和折扣派生的产品的销售价格。
  • 重新组织所有代码(T-SQL 和 VB/VBA 客户端代码),以便只有“包装器” View 直接引用表。
    因此,例如,即使应用程序或存储过程需要从表中插入/更新/删除记录,它们也会针对相应的“表包装器” View 执行此操作,而不是直接针对表。

  • 所以,基本上这是关于 通过 View 将所有表与系统其余部分隔离 .
    这种方法似乎提供了很多好处,尤其是从可维护性的角度来看。例如:
  • 当要重命名表列时,无需立即重写所有受影响的客户端代码即可完成。
  • 实现派生属性更容易(比使用计算列更容易)。
  • 您可以有效地为列名设置别名。

  • 显然,所有这些好处都必须付出一定的代价,但我不确定我是否看到所有潜伏在那里的渔获物。
    有人在实践中尝试过这种方法吗?主要的陷阱是什么?
    一个明显的缺点是维护“包装器” View 与其对应表同步的成本(表中的新列也必须添加到 View 中;从表中删除的列也必须从 View 中删除;等等.)但是对于使整个代码库更具弹性而言,这个价格似乎很小而且很公平。
    有谁知道任何其他更强大的缺点?
    例如,使用所有这些“包装器” View 而不是表很可能会产生一些不利的性能影响,但是这种影响是否足够大而值得担心?此外,在使用 ADODB 时,即使仅基于几个连接表,也很容易获得不可更新的记录集;那么,“包装器” View 会让事情变得更糟吗?等等等等...
    任何评论(尤其是分享的真实经验)将不胜感激。
    谢谢!

    附言我踩到了以下讨论“包装器” View 思想的旧文章:
    The Big View Myth
    本文建议避免上述方法。但是......我在文章中并没有真正看到反对这个想法的任何好的理由。恰恰相反,在创建 View 的充分理由列表中,几乎每一项都正是为每个表创建“包装器” View 如此诱人的原因(尤其是在遗留系统中,作为重构过程的一部分) )。
    这篇文章真的很旧(1999 年),所以无论当时的理由是好的,现在可能不再好(反之亦然)。听到最近考虑或什至尝试过这个想法的人,使用最新版本的 SQL Server 和 MS Access 会非常有趣......

    最佳答案

    在设计数据库时,我更喜欢以下几点:

  • 代码不能直接访问表(但可以从存储过程、 View 和函数访问)
  • 每个表的基本 View ,包括所有列
  • 每个表的扩展 View ,包括查找列(类型、状态等)
  • 所有更新的存储过程
  • 任何复杂查询的函数

  • 这允许 DBA 直接使用表(添加列、清理内容、注入(inject)数据等)而不会干扰代码库,并且它将代码库与对表所做的任何更改(临时或其他)隔离开来

    以这种方式做事可能会导致性能下降,但到目前为止它们并不显着 - 而且绝缘层的好处已经多次挽救了生命

    关于SQL Server 2005 : Wrapping Tables by Views - Pros and Cons,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/237601/

    相关文章:

    sql - 在 SQL Server 2008 中跨列返回最大值

    sql - 在单个查询中获取不同表的不同列的总和

    sql-server - SQL 服务器 : how to sort by creation date with no designated column

    database - 为什么从 Elasticsearch 检索数据比从 PostgreSQL 检索数据快得多?

    mysql - 在 SELECT 期间确定另一个表中相关行的数量 (0 - n)

    php - 如何获得标记列表的第二个最大值?

    sql - 在 Postgresql 中的多个列上执行 WHERE IN

    arrays - Sequelize - 存储过程的多个结果集合并到一个数组中

    mysql - DBMS 中的批量收集 V/S 简单更新

    database - 当具有多个具有 Play Framework 的数据库时不能使用 save()