将SQL保存在c#源代码或Stored Procs中有哪些优点/缺点?我一直在和一个朋友讨论这个问题,我们正在做一个开源项目(c# ASP。网论坛)。目前,大多数数据库访问都是通过在c#中构建内联SQL并调用SQL Server DB来完成的。所以我在试着确定,对于这个特定的项目,哪个是最好的。

到目前为止,我有:

in Code的优点:

更容易维护-不需要运行SQL脚本来更新查询 更容易移植到另一个DB -没有pros到移植

存储Procs的优点:

性能 安全


当前回答

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

Although the caching and reuse of execution plans for ad-hoc queries has improved significantly in later editions of SQL server (especially 2005 and 2008) there are still far fewer issues with plan reuse when dealing with stored procedures than there are for ad-hoc queries. For example, SQL server will only re-use an execution plan if the plan text matches exactly - right down to comments and white space, for example, if each of the following lines of SQL were to be executed independently, none of them would use the same execution plan:

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,然后用@ id查询SQL Server将parametrise SMALLINT(或可能是一个非常小的整数),所以如果你然后执行相同的查询@ id的说4000,SQL Server将parametrise INT,而不会重用相同的缓存。

我认为还有其他一些问题,老实说,大多数问题都可以解决——特别是在SQL Server的后续版本中,但是存储过程通常会提供更多的控制。

其他回答

CON

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

然而,如果您有多个服务器运行您的代码,那么在您的程序中进行所有这些处理而不是sql-server,可能会允许您进行更多的扩展。当然,这并不适用于只进行正常获取或更新的存储procs,而是适用于执行更多处理(如在数据集上循环)的存储procs。

PROS

Performance for what it may be worth (avoids query parsing by DB driver / plan recreation etc) Data manipulation is not embedded in the C/C++/C# code which means I have less low level code to look through. SQL is less verbose and easier to look through when listed separately. Due to the separation folks are able to find and reuse SQL code much easier. Its easier to change things when schema changes - you just have to give the same output to the code and it will work just fine Easier to port to a different database. I can list individual permissions on my stored procedures and control access at that level too. I can profile my data query/ persistence code separate from my data transformation code. I can implement changeable conditions in my stored procedure and it would be easy to customize at a customer site. It becomes easier to use some automated tools to convert my schema and statements together rather than when it is embedded inside my code where I would have to hunt them down. Ensuring best practices for data access is easier when you have all your data access code inside a single file - I can check for queries that access the non performant table or that which uses a higher level of serialization or select *'s in the code etc. It becomes easier to find schema changes / data manipulation logic changes when all of it is listed in one file. It becomes easier to do search and replace edits on SQL when they are in the same place e.g. change / add transaction isolation statements for all stored procs. I and the DBA guy find that having a separate SQL file is easier / convenient when the DBA has to review my SQL stuff. Lastly you don't have to worry about SQL injection attacks because some lazy member of your team did not use parametrized queries when using embedded sqls.

这样想

你有4个web服务器和一堆使用相同SQL代码的windows应用程序 现在您意识到SQl代码有一个小问题 所以你宁愿...... 在一个地方改变过程 或 将代码推送到所有的网络服务器上,重新安装所有Windows盒子上的所有桌面应用程序(单击一次可能会有帮助)

我更喜欢存储过程

它也更容易做一个过程的性能测试,把它放在查询分析器 设置io/time on统计信息 设置showplan_text,瞧

不需要运行分析器来查看到底调用了什么

这只是我的小意思

当存储过程被用于应用程序和数据库之间时,它们是最糟糕的。上面提到的使用它们的许多原因都可以由视图更好地处理。

有关安全的论点是站不住脚的。它只是将安全问题从应用程序转移到数据库。代码就是代码。我曾见过一些存储过程从应用程序中获取SQL,并使用它构建容易受到SQL注入攻击的查询。

一般来说,它们往往会在所谓的数据库开发人员和所谓的应用程序开发人员之间造成裂痕。实际上,所有编写的代码都是应用程序代码,只是执行上下文的不同。

使用丰富的SQL生成库,如LINQ, Rails ActiveRecord或Hibernate/NHibernate,使开发更快。在混合中插入存储过程会降低速度。

in Code的优点: 更容易维护-不需要运行SQL脚本来更新查询 更容易移植到另一个DB -没有pros到移植

实际上,我觉得你搞反了。恕我直言,在代码中维护SQL是痛苦的,因为:

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

把Stored Procs看作你从数据库对象中调用的方法——它们更容易重用,只有一个地方可以编辑,而且如果你确实更改了数据库提供程序,更改发生在你的Stored Procs中,而不是在你的代码中。

也就是说,存储过程的性能增益是最小的,正如Stu在我之前说过的,你不能在存储过程中设置断点(目前)。

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

存储过程的更多优点:

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