我应该使用存储过程来执行复杂的SELECT查询吗?

时间:2010-02-15 23:06:07

标签: php oracle stored-procedures

我正在研究一个相当复杂的SELECT查询。我有几个分层查询嵌套在一个SELECT中,而且管理起来非常困难。

我遇到了一些我的内联视图需要在多个地方执行的地方,所以在存储过程开始时执行那些一次然后对它进行一些迭代似乎是一个合理的想法。根据需要得出结果。

我想知道是否有任何理由我不应该或不能执行通过我的PHP代码调用的Oracle存储过程,并将结果集作为OUT参数返回。我倾向于仅使用SP进行更新/删除/插入,但是这个查询的庞大规模和复杂性似乎需要分解。

如果没有任何技术问题,是否有任何好的或不好的评论?

4 个答案:

答案 0 :(得分:4)

  

我正在研究一个相当复杂的SELECT查询。我有几个分层查询嵌套在一个SELECT中,而且管理起来非常困难。

好的,但为什么存储过程?为什么不创建一个视图呢?

  

我遇到了一些我的内联视图需要在多个地方执行的地方,所以在存储过程开始时执行那些一次然后对它进行一些迭代似乎是一个合理的想法。根据需要得出结果。

再次 - 视图的优秀用例。

  

我想知道是否有任何理由我不应该或不能执行通过我的PHP代码调用的Oracle存储过程,并将结果集作为OUT参数返回。   如果没有任何技术问题,是否有任何好评或不好的评论?

好吧,我不想开始宗教战争,我不想建议不适用于你的案件。但是这里有:

  • 我倾向于避免存储过程的一个原因是可移植性 - 我的意思是主要是数据库可移植性。众所周知,存储过程语言在dbs中是不可移植的,而像Oracle软件包这样的内置库在这方面会让事情变得更糟。
  • 存储过程从数据库服务器获取一些额外的处理能力。这使得整个应用程序的扩展变得更加困难:如果由于存储过程导致数据库服务器的容量耗尽,并且您需要升级harware甚至购买额外的oracle软件许可证,那我就不会高兴了露营者,特别是如果我本可以买便宜的网络服务器/ php盒而不是做计算。

我会选择存储过程的原因:

  • 语言可移植性。如果数据库可移植性不是一个问题,但您确实希望在多个应用程序中重用逻辑,或者必须能够使用不同语言进行编码,那么存储过程可能会节省您编写特定于语言的数据库调用代码。
  • 复杂的权限方案。存储过程为您提供了额外级别的权限,因为您可以使用存储过程的定义者或所有者的特权来执行该过程。有时,这解决了用户需要使用某些表的问题,但不允许直接访问它们。
  • 保存rountrips:如果你必须处理复杂的多语句事务,将它们放在存储过程中可以节省应用程序和数据库之间的rountrips,因为执行存储过程只需要一个rountrip。有时这可以让你获得更多的表现。

我想再次强调,在所有这些场景中,我仍然建议不要将所有程序逻辑放在存储过程中。数据库最适合存储和检索数据,像php / java / perl这样的语言/选择你的毒药更能处理它。

答案 1 :(得分:2)

如果您多次使用相同的内联视图,则它是with clause

的理想选择

答案 2 :(得分:2)

PHP可以使用Ref Cusrors处理从存储过程返回的结果集。 Oracle+PHP Cookbook has an example

所以没有任何技术障碍,但正如你从各种答案中可以看到的那样,你的问题有一些哲学方面。我想我们可以同意,如果您已经在存储过程中包装了一些SQL语句 - 您就是这样 - 那么您不会通过扩展“更新/删除/插入”来包含选择来大大损害系统的可移植性。

然后相关的问题变成“你应该嵌入这个特定查询使用存储过程吗?”答案恰恰取决于你的意思:

  

这个庞大的规模和复杂性   查询似乎需要被打破   下来。

将大型查询解构为几个较小的查询,然后在PL / SQL中将结果拼接在一起是诱人的,但应谨慎对待。这会降低应用程序的性能,因为PL / SQL比SQL具有更多的开销。使查询更具可读性并不是一个很好的理由:您需要确保复杂性对代码的运行产生实际和不利影响。

使用存储过程而不是视图的一个很好的理由可能是,如果要通过在查询主体中使用绑定变量或动态SQL来扩展查询的适用性。

对您的问题的确切答案需要有关查询性质的更多详细信息以及您正在考虑使用的简化技术。

答案 3 :(得分:1)

您可以查看subquery factoring,这可能会提高查询的可读性。 将单个SQL查询拆分为更具程序性的解决方案的一个风险是您失去了读取一致性。因此,您希望确保在程序运行时更改数据的人不会破坏它。您可能希望在过程调用的持续时间之前锁定表。这看起来很激烈,但如果你非常确定数据是静态的,如果不是那么会产生难看的副作用,那么它就是一个解决方案。

通常,如果一个SQL语句足够复杂,它可能无法在数据库之间移植,所以我不担心这个方面。

视图可以是隐藏复杂性的一个很好的选择,但隐藏复杂性的缺点是人们开始做一些看似“简单”但却非常复杂并且无法按预期工作的事情。您还可以获得另一个要考虑授予的对象等。[编辑:正如Roland所评论的那样,这同样适用于存储过程,视图,对象类型等。]

如果您希望返回大型结果集,则应考虑pipelined table function。这样,您可以避免同时在Oracle会话中使用整个结果集。