一切都存储过程

时间:2009-07-10 08:43:08

标签: java .net stored-procedures

我与一位同事讨论了.NET应用程序(在SQL Server 2005数据库上)中存储过程(SP)的使用问题。 [他有微软的背景和我的Java - 可能相关或不相关]。

我必须插入在UI中捕获的数据。为此我会写一个SP并在.NET代码中使用它?这不是必需的,但使用SP的优缺点是什么?

另一种情况:

我正在维护一份城市名单。用户可以使用UI添加城市。如您所料,用户无法进入重复的城市。如果发生重复输入,将显示错误。这可以通过多种方式实现:

  1. 在我的代码中运行一个select查询以检查它是否已经存在,然后如果没有插入该城市,否则在UI上出现错误。
  2. 直接插入,由于唯一索引,系统会捕获SQLException。反省SQLException以检查违反了哪个唯一索引并显示相应的错误。
  3. 创建一个SP并在该句柄中处理上述逻辑,即检查重复和抛出错误或插入
  4. 哪一个是正确的方法? (欢迎链接到好的资源)。

5 个答案:

答案 0 :(得分:7)

首先,使用SP而不是adhoc SQL语句是个好主意,因为: 1)安全性 - 只需要授予执行sproc的权限,而不是基础表 2)可维护性 - 可以在SQL Server中修补SP,而无需重建/部署.NET代码以调整查询 3)性能 - 使用sprocs时执行计划缓存/重用可以提高性能(如果在.NET中直接使用参数化SQL,也可以完成) 4)网络流量(确定,可以忽略不计,但SP可以节省您通过网络传递整个SQL语句,特别是在大型查询时)

异常是昂贵的,所以尽量避免在可以阻止它时抛出异常。 我建议在尝试插入记录之前编写一个执行IF EXISTS检查的sproc,如果不存在则只插入。只需返回一个返回代码或输出参数,指示发生了什么。例如0 =插入OK,-1 =已存在

在一个sproc调用中完成所有操作以保存数据库往返(即不首先查询数据库以进行检查,然后发送另一个语句来执行INSERT)。使用EXISTS检查是最佳的检查方式。

答案 1 :(得分:7)

作为一般经验法则,如果应用程序是给定数据库模式的唯一用户,那么我建议使用直接SQL(即没有SP)。如果数据库在应用程序之间共享,则控制应用程序和共享数据之间的接口变得更加重要,定义此接口的最简单方法是通过存储过程控制对数据的访问。

SP的使用增加了系统的复杂性,除非有充分的理由,否则不应增加复杂性。它还会严重妨碍您的应用程序使用优秀的ORM工具。

但与所有经验法则一样,总有例外。

答案 2 :(得分:5)

我喜欢分离数据层和业务逻辑层的想法。因此,我没有将任何业务逻辑放在数据库中,而是放在我域中的代码中。

如果你正在使用像NHibernate这样的ORM,数据库的角色将自动成为一个存储而不是其他任何东西。当您开始在数据库和应用程序的另一部分上实现业务逻辑的一部分时,您需要小心!

最好的问候

答案 3 :(得分:2)

如果您打算编写一个sp来执行所有检查并插入(如果能够),那么为什么不返回修改的行数,如果它大于零,则表示您的方法是成功的。我会避免有一个例外,这个想法是不能插入不是特别的,只是不可取的。调用存储过程的插入方法可以读取输出参数,并告诉它调用者是否插入了任何内容。

答案 4 :(得分:1)

我认为没有单一尺寸的解决方案。如果您需要Java和.NET解决方案之间的公共代码,那么SQL中的SP可能是最佳选择。

过去,我避免使用任何存储过程,因为它使得在受控环境中部署变得更加困难。当然,您可以通过简单的方式在这里或那里更新程序,但在大型系统中,这可能更多的是诅咒而不是祝福。

这取决于您对环境的控制程度。例如我更愿意相信UAT和生产是一样的。即如果它在UAT中有效,它将在生产中起作用。

如果只有你们两个,那么它可能没关系,你将能够轻松修复环境之间的任何不一致(假设你有多个环境)

但是对于具有更多环境,多个区域,不同时区的开发人员的更复杂系统,您将希望尽可能简单地部署和回滚新系统。对于Java部署,只需更改符号链接并重新启动服务即可。

同时运行两个版本的软件也很容易,因此您可以在白天轻松完成最后一分钟的测试,转换并更改生产环境,而不是等待停机时间。也许在SQL中有一种简单的方法可以做到这一点,但我没有遇到过。

总结:首先就整个端到端流程的要求达成一致,然后找到匹配的解决方案,人们通常会从他们熟悉的解决方案开始,专注于一个方面来证明他们的选择。他们经常在项目的最后阶段发现一个令人头疼的要求,这个要求为时已晚,无法改变,但如果从一开始就考虑过它就会很简单。