【问题标题】:Are modifiable join views a reasonable design choice?可修改的连接视图是合理的设计选择吗?
【发布时间】:2011-07-29 12:04:17
【问题描述】:

明确地说,modifiable join view 我的意思是一个由两个或多个表连接构成的视图,它允许插入/更新/删除操作来修改任何/所有组件表。

这可能是 postgres 特定的问题,不确定。如果其他 DBMS 具有可修改的连接视图的特殊功能,我也很感兴趣,因为据我所知,它们在标准 SQL 中是不可能的。

我正在研究 postgres 架构,我最近的一些阅读表明可以使用替代规则 (CREATE RULE ... DO INSTEAD ...) 构建可修改的连接视图。可修改的连接视图似乎是可取的,因为它允许在接口后面隐藏强大的规范化,为经典抽象提供一种机制。规则是实施的唯一选择,因为目前triggers cannot be set on views

然而,我尝试设计的第一个可修改视图遇到了问题,我发现许多人认为非平凡的规则是有害的(请参阅 cmets 中指向 this SO answer 的链接)。另外,我在网络上找不到任何可修改加入视图的示例。

问题(编辑以在问题上加分):

  • 您对可修改的联接视图有任何经验吗?您能否提供一个具有选择/插入/删除/更新能力的具体示例?
  • 它们是否实用,即它们是否可以被透明地处理,而不必在地雷/黑洞周围踮着脚尖?
  • 就功能/工作量比和可维护性而言,它们是否是一个好的设计选择?

非常感谢有关此主题的任何示例/讨论的链接。谢谢。

【问题讨论】:

标签: sql postgresql rules


【解决方案1】:

我通常以“最后有效记录”的形式进行视图,只是隐藏和跟踪修改(如 wiki)
我看到的唯一缺点是:然后您将视图用作表格,并将其与任何内容连接,然后在“wheres”上使用它,然后在其上插入记录,依此类推,但在您身后与针对真实表的相同操作相比(更大更复杂),性能损失很多。我认为这取决于有多少人必须了解模式。确实,某些 DBMS 也承认对视图进行索引,但我认为无论如何您都会损失大量的性能。对不起我的英语。

【讨论】:

    【解决方案2】:

    我从未使用过任何类型的可修改视图,但是当您询问它们是否是“合理的设计选择”时,我是否可以建议一种替代设计选择,在不需要可修改视图的情况下具有许多好处:Transactional API

    基本上这相当于:

    • 用户无权访问表,根本无法发出insertupdatedelete 语句
    • 用户可以访问表示定义良好的事务的函数 - 在最简单的级别上,这些函数可能只执行单个 DML,但通常不会。重要的是它们映射到“业务”意义而非“数据库”意义的事务
    • 对于查询,用户可以访问(不可修改的)视图

    【讨论】:

      【解决方案3】:

      是的,我对一般可更新视图有一些经验。我认为它们在 PostgreSQL 中很实用。与所有设计选择一样,它们可能是一个不错的选择,也可能是一个糟糕的选择。

      我发现它们在处理超类型/子类型表时特别有用。我为每个子类型创建一个视图;视图将子类型连接到超类型。撤销对基表的权限,为视图编写规则,并仅授予客户端代码访问视图的权限。然后,客户端代码完成的所有数据操作都会通过视图和在它们上定义的规则。

      我认为规则与任何其他环境中的任何其他功能都没有真正的不同。 环境,我指的是 C、C++、Java、Ruby、Python、Erlang 和 BASIC,而不仅仅是 dbms 环境。

      使用语言的优点。避免坏的。

      “不要使用 malloc()”是个坏建议。 “总是检查 malloc() 的返回值”是个好建议。 “永远不要使用规则”是个坏建议。 “避免以已知行为有问题的方式使用规则”是个好建议。超类型/子类型表视图所需的规则简单易懂。他们不会行为不端。

      在理论层面,视图提供逻辑数据独立性。但这只有在视图可更新的情况下才有可能。 (并且许多视图应该可以直接由数据库引擎更新,无需任何规则或触发器。)

      【讨论】:

        【解决方案4】:

        【讨论】:

        • 我已经看过你的博客文章,内容丰富。一旦 pg 9.1 发布,触发器+视图将非常好。
        【解决方案5】:

        我将它们用作 ORM 的替代品。我认为只要您不通过数据库到处乱扔它们,它们就很容易理解。我为应用程序定义了一个模式,然后该模式中的任何视图都是该应用程序的方法和操作。此后,客户端代码大部分可以自动化,因为视图提供了我编写通用客户端代码所需的抽象。

        人们指出,规则重写不是一个真正的表(但它是假装的),这使得编写会破坏的东西成为可能。这是可能的,但我还没有遇到过。这个想法是隐藏重写中的复杂性,然后只使用 no joins 进行简单的删除和更新。如果事实证明需要连接 - 是时候重写规则了,而不是顶级查询。

        最后,我发现它是一种非常紧凑的数据库编写方式。所有与之交互的方式都被写成规则。任何连接都不应访问真实表。您的业​​务逻辑非常明确。如果视图没有针对它的 UPDATE 规则 - 它不能被更新期间。由于您已经在数据库级别而不是客户端级别编写了所有这些内容,因此它不依赖于 Web 框架或特定语言。这为您希望如何连接到数据库带来了很大的灵活性。想象一下,您使用了 Web 框架,但随着时间的推移,您需要直接访问数据库以获取另一个来源。直接访问还将绕过您辛辛苦苦制定的所有 ORM 业务规则。使用您可以公开的规则编写接口,该接口无需担心新连接会破坏数据。

        如果人们说你真的可以和他们一起建立一个数据库 - 那么当然 - 你当然可以。但你也可以用其他一切。如果人们说你根本不能使用它们而不把事情搞砸,那我不同意。

        【讨论】:

          【解决方案6】:

          我知道在 SQL Server 中,如果您更新视图,则无论如何都必须将更改限制为仅一个表,这使得在我看来使用视图进行更新毫无用处,因为您必须知道哪些字段与哪些表一起使用。

          如果您想将信息抽象出来,而不必担心插入和更新的数据库结构,ORM 可能比视图做得更好。

          【讨论】:

          • 您可以在视图上放置INSTEAD OF 触发器,它可以选择将哪些数据写入哪些基础表。我自己从来没有做过,我认为你必须有一个非常很好的理由来为系统添加这种级别的复杂脆弱性
          【解决方案7】:

          我个人的偏好是仅将视图用于读取数据,(实际上)从不用于插入或更新。通过从根本上重新规范化数据库中的数据(听起来像您正在做的事情),您可能会创建一个很难长期测试和维护的系统。

          如果可能,请考虑将非规范化数据映射回应用程序代码中某处的正常模式,并在单个事务中以这种方式(恕我直言)将其提供给数据库。

          【讨论】:

            猜你喜欢
            • 2011-04-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-04-03
            • 1970-01-01
            相关资源
            最近更新 更多