哪个更好:即时查询还是存储过程?

假设不pipe用什么原因都不能使用Linq,将查询放在存储过程中是一种更好的做法,还是对数据库执行临时查询(比如说Sql Server)?

以我的经验主要写WinForms客户端/服务器应用程序这些是我得到的简单的结论:

使用存储过程:

  1. 对于任何复杂的数据工作。 如果你要做一些真正需要游标或临时表的事情,通常在SQL Server中最快。
  2. 当你需要locking对数据的访问时。 如果你不给用户(或者angular色或者其他)的表访问权限,你可以确保与数据交互的唯一方法是通过你创build的SP。

使用即席查询:

  1. 对于CRUD,当您不需要限制数据访问(或以其他方式进行)时。
  2. 对于简单的search。 为一堆search条件创buildSP是一个痛苦,难以维护。 如果你可以生成一个合理的快速search查询使用。

在我的大部分应用程序中,我都使用了SP和ad-hoc sql,但是我发现我使用SP的方式越来越less,因为它们最终变成了像C#一样的代码,只是更难于进行版本控制,testing和维护。 我会build议使用专门的SQL,除非你可以find一个特定的原因不。

除了SQL Server之外,我不能说任何其他的东西,但是性能参数在那里不是非常有效,除非你在6.5或更早的版本。 现在,SQL Server已经caching了临时执行计划。

存储过程代表了封装对数据库采取的行动的软件合同。 程序中的代码,甚至数据库本身的模式都可以改变,而不影响编译和部署的代码,只是程序的input和输出保持不变。

通过将查询embedded到应用程序中,您可以将自己与数据模型紧密结合。

出于同样的原因,简单地创build存储过程对于数据库中的每个表只是CRUD查询也不是好习惯,因为这仍然是紧耦合。 程序应该是体积庞大,粗粒度的操作。

从安全angular度来看,禁止应用程序中的db_datareader和db_datawriter并且只允许访问存储过程是一种很好的做法。

我认为这是必须维护数据库的人和开发用户界面的人之间的基本冲突。

作为一名数据人员,我不会考虑使用通过即席查询访问的数据库,因为他们难以有效调整或pipe理。 我怎样才能知道什么影响模式的变化将有? 此外,我不认为用户应该永远被允许直接访问数据库表出于安全的原因(我不只是指SQL注入攻击,而且因为它是一个基本的内部控制,不允许直接的权利,并要求所有的用户只使用为应用程序devise的过程,这是为了防止可能的欺诈行为,任何允许直接插入,更新或删除表的权限的金融系统都有很大的欺诈风险,这是一件坏事。

数据库不是面向对象的,从数据库的angular度来看,从面向对象的angular度来看,好的代码是非常糟糕的。

我们的开发人员告诉我们,他们很高兴我们所有的数据库访问都是通过proc进行的,因为它能够快速修复以数据为中心的错误,然后在生产环境中简单地运行proc,而不是创build一个新的代码分支并重新编译重新加载到生产。 我们要求我们所有的过程都在颠覆,所以源代码控制不是问题。 如果它不在Subversion中,它会周期性地被dbas丢弃,所以使用Source Control没有任何阻力。

存储过程肯定是要走的路……它们被编译,事先有执行计划,你可以对它们进行权限pipe理。

我不明白存储过程的整个源代码pipe理问题。 你一定可以控制他们,如果只是你有点纪律。

总是从作为存储过程源的.sql文件开始。 一旦你写了你的代码,把它放在版本控制。 下一次你想编辑你的存储过程时,从你的源代码控制比你的数据库。 如果你遵循这个,你将拥有和你的代码一样的源代码控制。

我想在这里引用Oracle的Tom Kyte …这里是他编写代码的规则…虽然有点不相关,但是我很高兴知道。

  1. 从PL / SQL中的存储过程开始
  2. 如果您认为在PL / SQL中使用存储过程无法完成某些操作,请使用Java存储过程。
  3. 如果您认为使用Java存储过程无法完成,请考虑使用Pro * c。
  4. 如果您认为使用Pro * C无法实现某些function,则可能需要重新考虑需要完成的工作。

在我们的应用程序中,有一层提供查询内容的代码(有时是对存储过程的调用)。 这使我们能够:

  • 轻松拥有版本控制下的所有查询
  • 使不同数据库服务器的每个查询都需要进行任何更改
  • 消除了通过我们的代码重复相同的查询代码

访问控制是在中间层而不是在数据库中实现的,所以我们不需要在那里存储过程。 这在某些方面是临时查询和存储过程之间的中间道路。

我从不同的post回答:存储过程更容易维护,因为:

  • 只要你想改变一些SQL,你不必重新编译你的C#应用​​程序
  • 你最终重用SQL代码。

代码重复是您尝试构build可维护的应用程序时可以做的最糟糕的事情!

当发现需要在多个地方纠正的逻辑错误时会发生什么? 你更容易忘记改变你复制和粘贴你的代码的最后一个位置。

在我看来,性能和安全性的收益是一个附加。 您仍然可以编写不安全/低效的SQL存储过程。

更容易移植到另一个数据库 – 没有过程端口

将所有存储过程编写成另一个数据库的脚本并不难。 事实上 – 这比导出表容易,因为没有主键/外键需要担心。

有两个有说服力的论点 – 存储过程都位于中央存储库,但(可能)很难迁移和临时查询更容易debugging,因为它们与您的代码,但他们也可能很难find码。

存储过程更高效的说法不再成立。 链接文本

做一个谷歌的存储过程与dynamic查询将显示任何方式的体面的论点,也许最好让你做出自己的决定…

应该尽可能地使用存储过程,如果你把SQL写成代码,你已经为自己设定了在期货头痛的问题。 写一个SPROC大概是在同一时间编写代码。

考虑一个在中等负载下运行良好的查询,但一旦进入全职生产,您的严重优化的查询将扰乱系统并使其陷入瘫痪。 在大多数SQL服务器中,您不是唯一使用它的应用程序/服务。 你的申请现在已经引起了一群愤怒的人在你家门口。

如果你在SPROC中有你的查询,你还可以让你友好的DBApipe理和优化,不用重新编译或打破你的应用程序。 请记住,DBA是这个领域的专家,他们知道该做什么而不是做什么。 利用他们更多的知识是有道理的!

编辑:有人说,重新编译是一个懒惰的借口! 是啊,让我们看看当你不得不重新编译和部署你的应用程序到数以千计的桌面时你感觉有多懒惰,这全都是因为DBA告诉你,你的即时查询耗费了太多的服务器时间!

有些事情需要思考: 谁需要存储过程?

显然,这是您自己的需求和偏好的问题,但在面向公众的环境中使用即席查询时需要考虑的一件事是安全性。 总是将它们参数化,并注​​意典型的漏洞,如SQL注入攻击 。

存储过程非常棒,因为它们可以在不重新编译的情况下进行更改。 我会尽量经常使用它们。

我只对基于用户inputdynamic生成的查询使用ad-hoc。

由于其他人提到的原因,也更容易调整与探查器或proc的一部分proc。 这样你就不必告诉别人运行他的应用程序来找出发送给SQL服务器的内容

如果您确实使用即席查询,请确保参数化

参数化的SQL或SPROC …从性能的angular度来看并不重要…您可以查询优化任何一个。

对于我来说,SPROC的最后一个好处是,我可以通过仅授予执行sprocs的login权限来消除很多SQL权限pipe理…如果使用参数化SQL,则使用连接string进行login具有更多的权限(编写ANY在他们有权访问的其中一个表上也可以select一种语句)。

我仍然喜欢参数化的SQL虽然…

我还没有发现使用即席查询的有力论据。 特别是那些与你的C#/ Java / PHP代码混合在一起的。

有人说重新编译是一个懒惰的借口! 是啊,让我们看看当你必须重新编译和部署你的应用程序到数以千计的桌面时,你觉得多么懒,全都是因为DBA告诉你,你的特定查询耗费了太多的服务器时间!

如果您允许将1000个桌面直接连接到数据库,那么它是一个好的系统架构吗

sproc性能参数是没有意义的 – 3个顶级的RDBM使用查询计划caching,并且已经有一段时间了。 它的logging…或者是1995年还是?

然而,在你的应用中embeddedSQL也是一个可怕的devise – 代码维护似乎是许多人缺less的概念。

如果应用程序可以从头开始使用ORM(新build应用程序之间的差距很小!),这是一个很好的select,因为您的类模型驱动您的数据库模型 – 并节省大量时间。

如果ORM框架不可用,我们已经采取了创buildSQL资源XML文件的方法,以根据需要查找SQLstring(它们随后由资源框架caching)。 如果SQL需要在代码中进行小的操作 – 如果需要对主要的SQLstring进行操作,我们将重新考虑这种方法。

这种混合方法可以让开发人员轻松pipe理(也许我们是less数,因为我的团队足够聪明,可以阅读查询计划),部署是SVN的简单结账。 此外,它使得切换RDBM变得更加简单 – 只需要换出SQL资源文件(当然不像ORM工具那样容易,但是连接到遗留系统或不支持的数据库)

取决于你的目标是什么。 如果你想检索一个项目列表,并且在应用程序的整个运行过程中发生一次,那么使用存储过程可能是不值得的。 另一方面,重复执行并花费相对较长时间执行的查询是数据库存储的绝佳select,因为性能会更好。

如果你的应用程序几乎完全存在于数据库中,那么存储过程是一件容易的事情。 如果您正在编写一个桌面应用程序,而数据库只是切合其重要性,则临时查询可能是一个更好的select,因为它将所有代码保存在一个地方 。

@Terrapin:我认为你的断言,你不必重新编译你的应用程序进行修改,使存储过程更好的select是一个不起动。 可能有select存储过程而不是特别查询的原因,但是如果没有其他任何引人注目的事情,编译问题似乎是懒惰而不是真正的原因。

我的经验是,90%的查询和/或存储过程根本不应该写(至less是手工)。

数据访问应该以某种方式自动生成。 您可以决定是否想要在编译时或在运行时dynamic生成过程,但是如果要将列添加到表(属性到对象),则只应修改一个文件。

如果您允许将1000个桌面直接连接到数据库,那么它是一个好的系统架构吗

不,显然不是,这可能是一个不好的例子,但我想我要说明的一点很清楚,你的DBA看pipe你的数据库基础设施,这是他们的专业知识,在代码中填充SQLlocking了他们的大门和他们的专业知识。

我更喜欢在程序代码中保留所有数据访问逻辑,其中数据访问层执行直接的SQL查询。 另一方面,数据pipe理逻辑我以触发器,存储过程,自定义函数的forms放入数据库中。 一个我认为值得关注的数据库例子是数据生成 – 假设我们的客户有一个FirstName和一个LastName。 现在,用户界面需要一个DisplayName,它是从一些非平凡的逻辑派生而来的。 对于这一代,我创build了一个存储过程,然后每当更新行(或其他源数据)时由触发器执行。

似乎有一种常见的误解,即数据访问层是数据库,所有关于数据和数据访问的内容都是“因为”。 这是完全错误的,但是我看到很多来自这个想法的devise。 虽然也许这是一个本地的表型。

看到那么多devise不好的人之后,我可能会关掉SP的想法。 例如,我参与的一个项目对每个表和他们遇到的每个可能的查询都使用了一组CRUD存储过程。 在这样做的时候,他们只是添加了另一个完全没有意义 甚至想到这样的事情也是痛苦的。

这些天我几乎没有使用存储过程。 我只将它们用于复杂的SQL查询,不能轻易在代码中完成。

其中一个主要原因是因为存储过程对于OR映射器来说效果不佳。

现在,我认为你需要一个很好的理由来编写一个不使用某种OR映射器的业务应用程序/信息系统。

存储过程作为代码块工作,以代替专用查询,它工作的很快。 另一件事是存储过程给重新编译选项,你只是使用这个存储过程的SQL最好的部分没有这样的adhoc查询。

在查询和存储过程中的一些结果是不同的,这是我的个人经验。 使用cast和covert函数来检查这个。

必须使用大型项目​​的存储过程来提高性能。

我在我的项目中有420个程序,对我来说工作正常。 我在这个项目上工作了三年。

所以只能使用任何交易的程序。