代码之家  ›  专栏  ›  技术社区  ›  Alex J

当服务器不在您的控制之下时,存储过程是一个好主意吗?

  •  4
  • Alex J  · 技术社区  · 15 年前

    是否有任何方法可以确保存储过程在软件级别上的一致性,从而确保它们将执行预期的操作?

    我不愿意使用存储过程,因为只要您具有对计算机的管理权限和Management Studio Express的副本,就可以轻松地读取和修改存储过程。在许多客户机拥有服务器的安装环境中,这是一个常见的环境,以前的经验告诉我,客户机(或竞争对手)不能被信任而将他们肮脏的手从数据库中移开。

    如果一个存储过程可以修改为执行任何操作,除非软件不断地进行检查,否则它可以静默地执行不应该执行的操作,而这将是不明智的。这让我感到非常不舒服——知道我无法控制软件的功能。

    这是一个有效的问题吗?

    7 回复  |  直到 15 年前
        1
  •  3
  •   Paul Nearney    15 年前

    它可以使用 WITH ENCRYPTION 提示-存在一些缺点,例如存储过程很难解密。

    另一种选择是使用ORM工具(或类似工具),动态生成SQL代码,例如Linq to SQL/实体、nHibernate等。

    或者,您可以确保客户机知道,如果在数据库级别进行了任何修改,系统将不再受支持——这可能足够激励他们不要干预。

        2
  •  3
  •   paxdiablo    15 年前

    老实说,如果它们有管理权限,存储过程只是它们破坏软件的众多方法之一。为什么不直接向客户机说明,如果他们在存储过程中到处都是,那么他们就不受支持。如果他们提出问题,让他们运行您的脚本,将存储过程转储到一个文件中,并让他们将其发送给您。

    任何变化都意味着你将修复它,但在他们的一角,而不是你的,因为他们造成了问题。

    在检查方面,我唯一能想到的就是用已知数据运行存储过程,并确保它返回您认为应该返回的数据。但这在他们的数据库中可能很难实现。

        3
  •  1
  •   S.Lott    15 年前

    “这是一个有效的问题吗?”

    对。存储过程是维护的噩梦,即使在本地管理的服务器上也是如此。

    你真的不需要它们。将应用程序设计为使用存储过程。设计紧凑、简短的过程元素,就好像它们将作为存储过程实现一样。然后用您选择的目标语言实现它们——它的运行速度和存储过程一样快。(在某些情况下,速度更快。)

    有些人有传闻称存储过程很快。这些轶事从来都不是数据库外部的集中事务与存储过程之间的直接比较。轶事总是将一些杂乱无章的垃圾程序与使用存储过程的修订版进行比较。

    它正在创建可提高性能的集中事务。这也可以在您的应用程序中完成。

        4
  •  0
  •   Tamas Czinege    15 年前

    我不太明白你的想法。为什么你的竞争对手可以直接访问你的数据库,这样他们就会把事情搞砸?

    如果用户在不咨询您的情况下对数据库进行手动修改,您如何可能支持您的应用程序?

    那么,除了正确地设置存储过程特权,您还应该将所有存储过程置于源代码管理中,并编写一个简单的脚本,删除所有(用户创建的)存储过程,并用正确的存储过程填充数据库。每当您觉得有人弄乱了您的存储过程时,您只需运行该脚本。您甚至可以将其作为计划作业运行。

    但坦率地说,您不应该授予任何人直接访问数据库的权限。

        5
  •  0
  •   Ayresome    15 年前

    当然,这是一个值得关注的问题。 如果您担心存储过程被更改,那么您可能也应该担心数据库的其他部分!

    您当然应该对存储过程进行比平时更具防御性的编程。当你完全控制了内容的时候,总是有一种诱惑把它当作可信的媒介。例如:在调用参数之前检查参数是否符合预期,检查字段长度是否符合预期等。

    我同意上面的pax,这是通过联系人最好处理的;如果客户通过“摆弄”破坏数据库,那么他们将不得不在之后支付修复费用。

    您总是可以在启动时或任何时候检查存储过程长度的代表性样本——如果不匹配,您可以对用户进行管理。

        6
  •  0
  •   Scott Whitlock    15 年前

    如果你给了他们管理权(普通),那么你就没办法阻止他们。但是,有一些很好的工具,比如Redgate SQL Compare,可以让您比较2个数据库模式(比如它应该是什么和现在是什么的快照),它会立即告诉您是否有任何更改,以及它们是什么。

    如果你知道用户要添加他们自己的东西,告诉他们一些基本规则,比如如果他们要添加表,在指定它为他们的表名中添加某种前缀。同样的事情也适用于存储过程…如果他们添加了新的,添加一些前缀来指定它们。

    如果您想让他们能够修改存储过程的功能,或者向表中添加列,那么您必须预先进行一些设计。您可以获取每个表,如Tablea,并添加一个名为Tablea_的具有一对一关系的子表。此表包含您可能希望允许他们访问与该主表相关的任何用户数据。您还可以为它们提供预定义的钩子,用于修改业务逻辑的功能。例如,每次添加新的此类行时,都可以调用传递新行数据的存储过程存根,它们可以在将其保存到数据库之前对其进行修改。显然,这很快就会变得复杂起来。

    处理这一问题的最佳方法是保持对客户的响应。如果他们想要一个改变,快速实施并获得报酬。

        7
  •  -1
  •   Learning    15 年前

    我使用存储过程作为“接口”。除了性能优势(存储过程几乎总是优于特殊查询),它还允许我的数据库和UI代码之间的松耦合。