将SQL保存在存储过程与代码中的优缺点是什么

时间:2008-08-18 19:54:39

标签: c# sql sql-server stored-procedures

在C#源代码或存储过程中保留SQL有哪些优点/缺点?我一直在与一位朋友讨论我们正在开发的一个开源项目(C#ASP.NET论坛)。目前,大多数数据库访问都是通过在C#中构建SQL内联并调用SQL Server DB来完成的。所以我试图确定哪个,对于这个特定的项目,最好。

到目前为止,我有:

代码中的优点:

  • 易于维护 - 无需运行SQL脚本来更新查询
  • 更容易移植到另一个数据库 - 没有移植到端口

存储过程的优点:

  • 性能
  • 安全

47 个答案:

答案 0 :(得分:179)

我不是存储过程的粉丝

  

存储过程更易于维护,因为:      *无论何时想要更改某些SQL

,都不必重新编译C#应用程序

当数据类型发生变化时,无论如何都会重新编译它,或者你想要返回一个额外的列,或者其他什么。您可以从应用程序下方“透明地”更改SQL的次数在整个

中非常小
  
      
  • 您最终会重用SQL代码。
  •   

编程语言,包括C#,有这个神奇的东西,称为函数。这意味着您可以从多个位置调用相同的代码块!惊人!然后,您可以将可重复使用的SQL代码放在其中一个中,或者如果您想获得真正的高科技,您可以使用为您执行此操作的库。我相信它们被称为对象关系映射器,现在很常见。

  

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

同意,这就是为什么storedprocs是一件坏事。将SQL重构和分解(分成较小的部分)代码转换为函数比将SQL转换为SQL块更容易吗?

  

你有4个网络服务器和一堆使用相同SQL代码的Windows应用程序现在你意识到SQl代码存在一个小问题所以你宁愿......在1个地方更改proc或推送所有网络服务器的代码,在所有Windows框上重新安装所有桌面应用程序(clickonce可能有帮助)

为什么您的Windows应用程序直接连接到中央数据库?这似乎是一个巨大的安全漏洞,并且它排除了服务器端缓存的瓶颈。它们不应该通过Web服务或类似于您的Web服务器进行连接吗?

那么,推送1个新的sproc或4个新的web服务器?

在这种情况下, 更容易推送一个新的sproc,但根据我的经验,95%的“推送更改”会影响代码,而不会影响数据库。如果你在那个月向网络服务器推送了20件事,并且在数据库中推送了1件,那么如果你将21件事情推送到网络服务器上,那么你几乎不会损失太多,而且数据库为零。

  

更容易审核代码。

你能解释一下吗?我不懂。特别是因为sprocs可能不在源代码控制中,因此无法通过基于Web的SCM浏览器等访问。

更多缺点:

Storedprocs存在于数据库中,该数据库在外部世界显示为黑盒子。想要将它们放入源代码控制中的简单事情就变成了一场噩梦。

还有一个纯粹的努力问题。如果你试图向你的CEO证明为什么只花费700万美元来建立一些论坛,那么将所有内容分解为million tiers可能是有意义的,但是否则为每一件小事创建一个存储过程只是额外的驴工无益。

答案 1 :(得分:99)

目前正在讨论其他几个主题。我是存储过程的一贯支持者,尽管正在介绍Linq到Sql的一些好的参数。

在代码中嵌入查询会将您与数据模型紧密联系在一起。存储过程是一种很好的合同编程形式,这意味着只要存储过程的输入和输出所代表的合同得以维持,DBA就可以自由地更改数据模型和过程中的代码。

当查询隐藏在代码中而不是位于一个易于管理的中央位置时,调整生产数据库可能非常困难。

[编辑]这是另一个current discussion

答案 2 :(得分:47)

在我看来,你不能在这个问题上投票赞成或不投票。这完全取决于您的应用程序的设计。

我完全投票反对在3层环境中使用SP,前面有一个应用服务器。在这种环境中,您的应用程序服务器可以运行您的业务逻辑。如果您另外使用SP,则会开始在整个系统中分发业务逻辑的实现,并且很难确定谁负责什么。最终,您将得到一个应用程序服务器,除了以下内容之外基本上什么都不做:

(Pseudocode)

Function createOrder(Order yourOrder) 
Begin
  Call SP_createOrder(yourOrder)
End

所以最后你的中间层运行在这个非常酷的4服务器集群上,每个集群都配备了16个CPU,它实际上什么都不做!多么浪费!

如果你有一个胖的gui客户端直接连接到你的数据库,或者甚至更多的应用程序,它是一个不同的故事。在这种情况下,SP可以作为某种伪中间层,将您的应用程序与数据模型分离,并提供可控制的访问。

答案 3 :(得分:44)

  

代码中的优点:

     
      
  • 易于维护 - 无需运行SQL脚本来更新查询
  •   
  • 更容易移植到另一个数据库 - 没有移植到端口
  •   

实际上,我认为你倒退了。恕我直言,SQL代码很难维护,因为:

  • 你最终在相关的代码块中重复自己
  • 许多IDE中不支持SQL语言,因此您只有一系列未经错误检查的字符串为您执行任务
  • 数据类型,表名或约束中的更改比将新数据库换成新数据库更为普遍
  • 随着查询复杂性的增加,您的难易程度会增加
  • 并测试内联查询需要构建项目

将Stored Procs视为您从数据库对象调用的方法 - 它们更容易重用,只有一个地方可以编辑,如果您更改数据库提供程序,更改将在您的存储过程中发生,而不是在你的代码中。

也就是说,存储过程的性能提升很小,因为Stu在我之前说过,你还不能在存储过程中设置一个断点。(/ p>

答案 4 :(得分:33)

<强> CON

我发现在扩展你的行为时,在存储过程中进行大量处理会使你的数据库服务器成为一个单一的不灵活点。

然而,如果您有多个运行代码的服务器,那么在您的程序中执行所有与sql-server相反的操作时,可能允许您扩展更多。当然,这不适用于仅执行常规获取或更新的存储过程,而是适用于执行更多处理(如循环数据集)的存储过程。

<强>赞成

  1. 表现可能值(避免通过DB驱动程序/计划重新创建查询解析等)
  2. 数据操作未嵌入到C / C ++ / C#代码中,这意味着我可以查看较少的低级代码。单独列出时,SQL不那么冗长,也更容易查看。
  3. 由于分离,人们可以更容易地找到并重用SQL代码。
  4. 在架构更改时更容易更改内容 - 您只需要为代码提供相同的输出,它就可以正常工作
  5. 更容易移植到其他数据库。
  6. 我可以列出我的存储过程的各个权限,并控制该级别的访问权限。
  7. 我可以将数据查询/持久性代码与我的数据转换代码分开。
  8. 我可以在我的存储过程中实现可更改的条件,并且很容易在客户站点进行自定义。
  9. 使用一些自动化工具将我的架构和语句转换为一起变得更容易,而不是在我的代码中嵌入我需要将其删除的时候。
  10. 当您在单个文件中包含所有数据访问代码时,确保数据访问的最佳实践更容易 - 我可以检查访问非性能表的查询或使用更高级别序列化的查询或选择*的代码等。
  11. 当在一个文件中列出所有模式更改/数据操作逻辑更改时,它变得更容易。
  12. 当SQL位于同一位置时,对SQL进行搜索和替换编辑会变得更加容易,例如:更改/添加所有存储过程的事务隔离语句。
  13. 我和DBA的家伙发现,当DBA必须审查我的SQL内容时,拥有一个单独的SQL文件会更容易/更方便。
  14. 最后,您不必担心SQL注入攻击,因为您的团队中的某些懒惰成员在使用嵌入式sqls时未使用参数化查询。

答案 5 :(得分:22)

存储过程的性能优势通常可以忽略不计。

存储过程的更多优点:

  • 防止逆向工程(当然,如果使用加密创建)
  • 更好地集中数据库访问
  • 能够透明地更改数据模型(无需部署新客户端);如果多个程序访问相同的数据模型,则特别方便

答案 6 :(得分:16)

我选择 代码 。我们构建了所有应用程序(包括Web和客户端)使用的数据访问层,因此从这个角度看它是干的。它简化了数据库部署,因为我们只需要确保表模式是正确的。它简化了代码维护,因为我们不必查看源代码和数据库。

我与数据模型的紧密耦合没有太大问题,因为我没有看到真正打破这种耦合的可能性。应用程序及其数据本质上是耦合的。

答案 7 :(得分:13)

存储过程。

如果错误滑动或逻辑稍微改变,则不必重新编译项目。此外,它允许从不同的来源访问,而不仅仅是您在项目中编码查询的地方。

我认为维护存储过程并不困难,您不应该直接在数据库中编码,而应先在单独的文件中编码,然后您可以在需要设置的任何数据库上运行它们。

答案 8 :(得分:13)

存储过程的优点

更容易审核代码。

耦合较少,因此更容易测试。

更容易调整。

从网络流量的角度来看,性能通常更好 - 如果你有一个游标或类似游戏,那么就没有多次访问数据库

您可以更轻松地保护对数据的访问,删除对表的直接访问,通过过程强制执行安全性 - 这也可以让您相对快速地找到更新表的任何代码。

如果涉及其他服务(例如Reporting Services),您可能会发现将所有逻辑存储在存储过程中更容易,而不是存储在代码中,并且必须复制它

<强>缺点:

难以为开发人员管理:脚本的版本控制:每个人都有自己的数据库,是与数据库和IDE集成的版本控制系统吗?

答案 9 :(得分:11)

在某些情况下,代码中动态创建的sql可以比存储过程具有更好的性能。如果你创建了一个存储过程(让我们说sp_customersearch)变得非常复杂,因为它必须非常灵活,你可能会在运行时在代码中生成一个更简单的sql语句。

有人可能会争辩说,这只是将一些处理从SQL移动到Web服务器,但总的来说这将是一件好事。

关于这种技术的另一个好处是,如果你正在查看SQL分析器,你可以看到你生成的查询并调试它比看到存储的带有20个参数的proc调用更容易。

答案 10 :(得分:9)

我喜欢存储过程,不知道有多少次我能够使用存储过程对应用程序进行更改,而该存储过程不会对应用程序产生任何停机时间。

Transact SQL的大粉丝,调优大型查询已被证明对我非常有用。大约6年内没有写过任何内联SQL!

答案 11 :(得分:8)

你列出了2个针对sprocs的专业点:

表现 - 不是真的。在Sql 2000或更高版本中,查询计划优化非常好,并且已缓存。我确信Oracle等会做类似的事情。我认为不再有针对性能的问题。

安全?为什么sprocs会更安全?除非您拥有一个非常不安全的数据库,否则所有访问都将来自您的DBA或您的应用程序。始终参数化所有查询 - 永远不要在用户输入内联内容,你会没事的。

无论如何,这是表现的最佳做法。

Linq绝对是我现在开展新项目的方式。请参阅此similar post

答案 12 :(得分:8)

@Keith

  

安全?为什么sprocs会更安全?

根据Komradekatz的建议,您可以禁止访问表(对于连接到数据库的用户名/密码组合)并仅允许SP访问。这样,如果有人获取数据库的用户名和密码,他们就可以执行SP,但无法访问表或数据库的任何其他部分。

(当然,执行sprocs可能会为他们提供他们需要的所有数据,但这取决于可用的sprocs。让他们访问表格可以访问所有内容。)

答案 13 :(得分:7)

以这种方式思考

你有4个网络服务器和一堆使用相同SQL代码的Windows应用程序 现在您意识到SQl代码存在一个小问题 所以你宁愿...... 将proc更改为1个位置 要么 将代码推送到所有Web服务器,在所有Windows框上重新安装所有桌面应用程序(clickonce可能有帮助)

我更喜欢存储过程

对proc进行性能测试也更容易,将它放在查询分析器中 设置统计io /时间 设置showplan_text on和voila

无需运行探查器即可确切了解所谓的

只是我的2美分

答案 14 :(得分:6)

我更喜欢在代码中保留它们(使用ORM,而不是内联或临时),因此它们可以被源代码控制所覆盖,而无需处理保存的.sql文件。

此外,存储过程本身并不安全。您可以使用sproc编写错误查询,就像内联一样容易。参数化内联查询可以像sproc一样安全。

答案 15 :(得分:6)

在安全性方面,存储过程更安全。有些人认为所有访问都是通过应用程序进行的。很多人都忘记的事情是,大多数安全漏洞都来自公司内部。想想有多少开发人员知道应用程序的“隐藏”用户名和密码?

此外,正如MatthieuF指出的那样,由于应用程序(无论是在桌面服务器还是Web服务器上)与数据库服务器之间的往返次数减少,性能可以大大提高。

根据我的经验,通过存储过程抽象数据模型也极大地提高了可维护性。作为过去必须维护许多数据库的人,当面对所需的模型更改时,能够简单地更改一两个存储过程并使更改对所有外部应用程序完全透明,这是一种解脱。很多时候,您的应用程序并不是唯一一个指向数据库的应用程序 - 还有其他应用程序,报告解决方案等,因此跟踪所有这些受影响的点可能是对表的开放访问的麻烦。

我还将检查放在加号列中,以便将SQL编程放在专门研究它的人手中,并使SP更容易隔离和测试/优化代码。

我看到的一个缺点是许多语言不允许传递表参数,因此传递未知数字值可能很烦人,而且某些语言仍然无法处理从单个存储过程中检索多个结果集(尽管后者在这方面不会使SP比内联SQL更差)。

答案 16 :(得分:6)

将您的应用代码用作最佳功能:处理逻辑 使用您的数据库以获得最佳效果:存储数据。

您可以调试存储过程,但您会发现在代码中更容易调试和维护逻辑。 通常,每次更改数据库模型时,都将重新编译代码。

此外,带有可选搜索参数的存储过程非常有用,因为您必须提前指定所有可能的参数,有时无法进行复杂搜索,因为您无法预测参数在搜索中重复的次数。

答案 17 :(得分:4)

我们现在使用Oracle DB的存储过程。我们也使用Subversion。所有存储过程都创建为.pkb&amp; .pks文件并保存在Subversion中。我以前做过在线SQL,很痛苦!我更喜欢我们在这里做的方式。创建和测试新的存储过程要比在代码中更容易。

答案 18 :(得分:4)

我参加过的Microsoft TechEd安全会议的建议之一,通过存储过程进行所有调用,并拒绝直接访问表。这种方法被称为提供额外的安全性。我不确定它是否值得为安全起见,但如果你已经在使用存储过程,它就不会受到伤害。

答案 19 :(得分:4)

我坚定地站在存储过程的一边,假设你没有作弊并在存储过程中使用动态SQL。首先,使用存储过程允许dba在存储过程级别而不是表级别设置权限。这不仅对于解决SQL注入问题,而且对防止内部人员直接访问数据库和更改内容至关重要。这是一种有助于防止欺诈的方法。除非通过严格的程序,否则不应访问包含个人信息(SSN,信用卡号等)或无论如何创建金融交易的数据库。如果您使用任何其他方法,您将为公司中的个人敞开数据库,以创建虚假的金融交易或窃取可用于身份盗用的数据。

存储过程比从应用程序发送的SQL更容易维护和性能调整。它们还允许dba查看数据库结构更改对数据访问方式的影响。我从来没有见过一个允许动态访问数据库的好dba。

答案 20 :(得分:4)

如果将其放入存储过程中,则更容易维护。如果涉及的逻辑很难在将来发生变化,那么当您有多个客户端连接时,将它放在数据库中绝对是个好主意。例如,我现在正在开发一个具有最终用户Web界面和管理桌面应用程序的应用程序,这两个应用程序共享一个数据库(很明显),并且我试图在数据库上保留尽可能多的逻辑。这是DRY principle的完美示例。

答案 21 :(得分:3)

显然,使用存储过程比在代码中构造SQL有几个优点。

  1. 您的代码实现和SQL彼此独立。
  2. 代码更易于阅读。
  3. 多次使用一次。
  4. 修改一次
  5. 无需向程序员提供有关数据库的内部详细信息。等等。

答案 22 :(得分:3)

SQL存储过程不会提高查询性能

答案 23 :(得分:3)

我不是存储过程的忠实粉丝,但我在一个条件下使用它们:

当查询非常庞大时,最好将其作为存储过程存储在数据库中,而不是从代码中发送。这样,不是从应用程序服务器向数据库发送大量字符串字符,而是仅发送"EXEC SPNAME"命令。

当数据库服务器和Web服务器不在同一网络上时(例如,Internet通信),这是过度的。即使情况并非如此,过多的压力也意味着大量浪费的带宽。

但是男人,他们管理得太糟糕了。我尽可能地避免它们。

答案 24 :(得分:3)

较小的日志

尚未提及的存储过程的另一个小专业人员:当涉及到SQL流量时,基于sp的数据访问会产生很多更少的流量。当您监控流量以进行分析和分析时,这变得非常重要 - 日志将更小且可读。

答案 25 :(得分:2)

我通常会写OO代码。我怀疑大多数人也可能这样做。在这种情况下,对我来说很明显,所有的业务逻辑 - 包括SQL查询 - 都属于类定义。拆分逻辑,使其部分驻留在对象模型中,部分位于数据库中,并不比将业务逻辑放入用户界面更好。

在早期的答案中已经说过很多关于存储过程的安全性好处。这些分为两大类:

1)限制对数据的直接访问。这在某些情况下肯定很重要,当你遇到一个时,那么存储过程几乎是你唯一的选择。根据我的经验,这些案例是例外而不是规则。

2)SQL注入/参数化查询。这个异议是一个红鲱鱼。内联SQL - 甚至是动态生成的内联SQL - 可以像任何存储过程一样完全参数化,并且可以在任何现代语言中轻松完成。这两种方式都没有优势。 (“懒惰的开发人员可能不会使用参数”并不是一个有效的异议。如果您的团队中的开发人员更喜欢将用户数据连接到他们的SQL而不是使用参数,那么您首先尝试教育他们,然后解雇他们如果这不起作用,就像开发人员会有任何其他不良的,明显有害的习惯一样。)

答案 26 :(得分:2)

我是SPROC代码的巨大支持者。最重要的原因是保持代码紧密耦合,然后紧接着是源代码控制的简易性,而没有很多自定义实用程序将其拉入。

在我们的DAL中,如果我们有非常复杂的SQL语句,我们通常将它们包含为资源文件并根据需要更新它们(这也可以是一个单独的程序集,并按每个数据库换出等等。)。 p>

这使我们的代码和我们的sql调用保存在同一个版本控件中,而不会“忘记”运行一些外部应用程序进行更新。

答案 27 :(得分:2)

到目前为止我还没有看到的东西:最了解数据库的人并不总是编写应用程序代码的人。存储过程为数据库人员提供了一种与程序员交互的方式,这些程序员并不真正想要了解SQL。大型 - 特别是遗留式 - 数据库并不是最容易理解的东西,所以程序员可能只是喜欢一个简单的界面来为他们提供他们需要的东西:让DBA弄清楚如何加入17个表来实现这一点。

话虽这么说,用于编写存储过程的语言(PL / SQL是一个臭名昭着的例子)非常残酷。它们通常不会提供您在当今流行的命令式,OOP或函数式语言中看到的任何细节。想想COBOL。

因此,坚持使用仅仅抽象出关系细节而不是那些包含业务逻辑的存储过程。

答案 28 :(得分:2)

@Terrapin - sprocs同样容易受到注射攻击。正如我所说:

  

始终对所有查询进行参数化 - 永远不要在用户输入内联内容,你会没事的。

这适用于sprocs和动态Sql。

我不确定不重新编译你的应用程序是一个优势。我的意思是,你已经对该代码(应用程序和数据库)进行了单元测试,无论如何再次上线。


@Guy - 是的,你是对的,sprocs让你控制应用程序用户,这样他们只能执行sproc而不是底层操作。

我的问题是:如果通过您的应用程序访问它,使用连接和具有有限更新/插入权限的用户等,是否会增加安全性或额外管理?

我的观点非常重要。如果他们已经将您的应用程序泄露到他们可以重写的程度,那么他们可以使用大量其他攻击。

如果动态内联代码,仍然可以针对这些sproc执行Sql注入,因此仍然适用黄金法则,所有用户输入必须始终进行参数化。

答案 29 :(得分:2)

存储过程 MORE 可维护,因为:

  • 无论何时想要更改某些SQL
  • ,都不必重新编译C#应用程序
  • 您最终会重用SQL代码。

代码重复是您在尝试构建可维护应用程序时可以执行的最差事情!

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

在我看来,表现&amp;安全收益是一个额外的加分。 您仍然可以编写不安全/效率低下的SQL存储过程。

  

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

在另一个数据库中编写用于创建的所有存储过程并不是很困难。事实上 - 它比导出表格更容易,因为没有主要/外键需要担心。

答案 30 :(得分:1)

我在其他答案中找不到的一点如下:

如果在您的环境中数据库及其架构是架构的核心,并且应用程序具有更多的卫星角色,则可以更有效地使用存储过程,这可能有助于为所有应用程序提供级别基础。需要访问数据库,从而减少代码重复(例如,您确定所有数据库访问应用程序将始终使用C#或其他.NET语言编写吗?)。

另一方面,如果应用程序具有更重要的角色,并且DB更多地充当应用程序的后备存储,那么通过提供更少的存储过程来减少代码重复可能是明智的。公共持久层,可能基于ORM工具/框架。

在这两种情况下,重要的是DB不被视为存储过程的方便存储库。将它们保存在版本控制系统中的源文件中,并尝试尽可能自动化它们的部署(这实际上对所有与模式相关的工件都有效)。

答案 31 :(得分:1)

我对存储过程的投票;作为接近数据的抽象层,对集合有效,可由许多“客户端”(客户端语言)重用。 T-SQL语言有点原始(我想这就是SO中大多数C#人员所接触到的),但Oracle的PL / SQL与任何现代编程语言都不相上下。

对于版本控制,只需将存储过程代码放在版本控制下的文本文件中,然后运行脚本在数据库中创建过程。

答案 32 :(得分:1)

没人提到单元测试!

如果你有一个saveOrder方法,你可以在里面调用几个方法,并为每个方法创建一个单元测试,但是如果你只是调用一个存储过程,则无法做到这一点。

答案 33 :(得分:1)

我更喜欢使用O / R Mapper,例如LLBLGen Pro

它为您提供了相对无痛的数据库可移植性,允许您使用强类型对象以与您的应用程序相同的语言编写数据库访问代码,并且在我看来,您可以更灵活地使用您处理数据的方式拉回来。

实际上,能够使用强类型对象是使用O / R Mapper的理由。

答案 34 :(得分:1)

当存储过程用于站在应用程序和数据库之间时,它们是最差的。上述使用它们的许多原因可以通过观点更好地处理。

安全论证是虚假的。它只是将安全问题从应用程序移动到数据库。代码是代码。我见过存储过程从应用程序中获取SQL并使用它构建受SQL注入攻击的查询。

通常,它们往往会在所谓的数据库开发人员和所谓的应用程序开发人员之间产生裂痕。实际上,所有编写的代码都是应用程序代码,它只是执行上下文的不同之处。

使用丰富的SQL生成库(如LINQ,Rails ActiveRecord或Hibernate / NHibernate)可以加快开发速度。在混合中插入存储过程可以减慢速度。

答案 35 :(得分:1)

我想再次使用存储过程进行投票(尽管在维护和版本控制时可能会引入麻烦),这是限制对基础表的直接访问以提高安全性的一种方式。

答案 36 :(得分:1)

SQL注入攻击正在上升。有人在您的网站上找到此代码并运行注入攻击非常容易。您必须始终 始终 参数化您的查询。最好永远不要在动态SQL查询上运行exec(@x)。使用内联SQL并不是一个好主意,IMO。

某些人认为,存储过程很麻烦,因为它们是另一组与代码保持分离的项目。但它们是可重用的,如果您最终在查询中发现错误,您可以在不重新编译的情况下修复它们。

答案 37 :(得分:1)

@Keith

  

安全?为什么sprocs会更安全?

存储过程提供SQL Injection攻击的固有保护。

但是,您没有受到完全保护,因为您仍然可以编写易受此类攻击攻击的存储过程(即存储过程中的动态SQL)。

答案 38 :(得分:0)

存储过程的首选项是因为: - 在系统运行时启用修复生产中的一些数据相关问题(对我来说这是一个数字) - DB与程序之间的清晰合同定义(关注点清晰分离) - 更好地移植到不同的数据库供应商(如果写得比代码更改通常只在SP端)。 - 更好地进行性能调整

缺点 - 如果WHERE子句在使用条件上有很大差异并且需要高性能,则会出现问题。

答案 39 :(得分:0)

存储过程的优点 1)。由于存储过程中的SQL本质上是静态的(大多数情况下),因此提高了安全性。这将防止SQL注入。 2)。可重用性。如果需要为多个应用程序/组件返回相同的数据,这可能是更好的选择,而不是重复SQL语句。 3)。减少客户端和数据库服务器之间的调用。

我不确定其他数据库,但您可以在主机上的db2中使用主机语言创建存储过程,这使它们非常强大。

答案 40 :(得分:0)

坚定地站在“存储过程对CRUD /业务逻辑使用不利”阵营。我理解报告,数据导入等方面的需要

Write up here...

答案 41 :(得分:0)

程序员希望他们的应用程序中的代码。 DBA希望它在数据库中。

如果你有两者,你可以使用存储过程在两者之间划分工作,程序员不必担心所有这些表如何连接在一起等等。(对不起,我知道你想要控制它们一切。)。

我们有第三方应用程序,允许在数据库中的视图或存储过程上创建自定义报告。如果我将所有逻辑放在另一个应用程序的代码中,我就无法重用它。如果您处于使用数据库编写所有应用程序的情况,这不是问题。

答案 42 :(得分:0)

存储过程可能比代码更容易在数据库和源代码控制系统之间失去同步。应用程序代码也可以,但在持续集成时不太可能。

数据库就是这样,人们不可避免地要改变生产数据库,只是为了摆脱困境。然后忘记在环境和源控制系统中同步它。生产数据库迟早会成为事实上的记录而不是源代码控制系统 - 你会遇到无法删除任何代码的情况,因为你不知道它是否被使用。

一个好的过程应该只允许通过适当的通道更改生产,这样你就可以从源头控制系统(无数据)从头开始重建数据库。但我只是说,因为它可以完成并且已经完成 - 在一瞬间,生产数据库的变化,来自大喊大叫的客户的呼叫,经理呼吸,等等。

使用存储过程运行即席查询很麻烦 - 使用动态sql(或ORM)更容易完成,这可能是我自己使用存储过程的最大缺点。

另一方面,存储过程在您进行更改但不需要重新部署应用程序代码的情况下很好。它还允许您在通过网络发送数据之前对数据进行整形,其中代码中的sql可能需要多次调用以进行检索而不是对其进行整形(尽管现在有多种方法可以运行多个sql语句并在单个“调用中返回多个结果集” “,就像ADO.NET中的MARS一样,导致可能有更多数据通过您的网络传播。

我不会购买任何有关性能和安全性的其他论据。无论是好的还是坏的,都是同样的控制。

答案 43 :(得分:0)

您的编程语言和应用程序框架很可能:

  • 高级,特别是与SQL相比
  • 易于通过自动化流程进行版本和部署,尤其是与SQL相比

如果这两个条件是两个,则跳过存储过程。

答案 44 :(得分:0)

我还没有找到一种在源代码管理中轻松维护存储过程的好方法,使其与代码库一样无缝。它不会发生。仅这一点就可以让我的代码中的SQL值得。现代系统的性能差异可以忽略不计。

答案 45 :(得分:0)

在我工作的地方,sproc的最大优点是,当时间到来时,我们有更少的代码移植到VB.NET(来自VB6)。并且它的代码更少,因为我们使用sprocs来处理所有查询。

当我们需要更新查询而不是更新VB代码,重新编译并在所有计算机上重新安装时,它也会有很大的帮助。

答案 46 :(得分:-1)

对于Microsoft SQL Server,您应尽可能使用存储过程来协助执行计划缓存和重用。为什么要优化计划重用?因为执行计划的生成相当昂贵。

尽管临时查询的执行计划的缓存和重用在SQL Server的后续版本(特别是2005年和2008年)中得到了显着改善,但在处理存储过程时计划重用的问题远远少于广告的问题。 -hoc查询。例如,如果计划文本与完全匹配,则SQL服务器将仅重复使用执行计划 - 直到评论和空格,例如,如果要执行以下每行SQL独立地,他们都不会使用相同的执行计划:

SELECT MyColumn FROM MyTable WHERE id = @id
select MyColumn from MyTable WHERE id = @id
SELECT MyColumn  FROM MyTable WHERE id = @id
SELECT MyColumn FROM MyTable WHERE id = @id -- "some comment"
SELECT MyColumn FROM MyTable WHERE id = @id -- "some other comment"

除此之外,如果您没有明确指定参数的类型,那么SQL Server很可能会出错,例如,如果您使用输入4执行上述查询,那么SQL Server将@id作为SMALLINT(或可能是TINYINT)进行参数化,因此如果您使用@id为4000执行相同的查询,SQL Server会将其作为INT参数化,并且不会重用相同的缓存。

我认为还存在一些其他问题,而且诚实地说,大多数问题都可以解决 - 特别是对于SQL Server的更高版本,但存储过程通常会为您提供更多控制。