假设我有两个将经常针对我的数据库运行的查询:
SELECT
UserID,
UserName,
UserGender
FROM Users
WHERE UserID = @User
SELECT
UserID,
UserName,
UserGender
FROM Users
WHERE UserName LIKE @Name + '%
它们应该在两个单独的存储过程中,还是只在一个使用 sp_executesql 动态创建语句的存储过程中?
如果它们在两个存储过程中,那么如果我想在 SELECT 语句中添加或删除列,我将需要修改这两个过程。如果我使用动态 SQL,那么我可能会牺牲少量性能。
在这种情况下,通过使用动态 SQL 可维护性和遵守 DRY 原则(不要重复自己)是否优先于存储过程的性能增益?
严格的 DRY 并不真正适用于数据库
我已经看到 DRY 被用作创建“重用”视图的理由。然后我们有观点加入观点等,并且表现不佳。
通常,类似的查询会以不同的方式使用。一个可能有聚合,一个可能没有,过滤器会有所不同(如上所述)。相似性并不能证明动态 SQL 的合理性,也不能证明视图的合理性。
在上面的特定情况下,我会考虑使用 IF 语句来捕获差异,特别是如果代码是由相同的搜索页面或表单发出的:您具有基于用法的相似性,而不仅仅是使用相同的列和表。
此外,您还需要考虑安全性。
动态 SQL 需要 EXECUTE AS(权限升级)或对基表的权限。使用普通存储过程不需要这样的权限。
您也可能有不同的客户端代码:我们为每个客户端存储过程(模式控制权限)。您是否要将所有表的选择权限授予所有客户?
我不确定动态 SQL 是这里唯一的答案,但如果您的搜索参数变得相对复杂,有时它可能是最好的解决方案。在您提出的简单情况下,为什么不接受一个或两个参数的简单查询...
但是,如果搜索条件变得复杂,您将不得不考虑动态 SQL,因为 SQL Server 会更幸运地尝试为不同版本的查询优化计划,并尝试创建一个满足所有不同搜索条件的神奇计划。
您可以制作单独的存储过程,通过用户各自的搜索方法识别用户,只返回主键值,然后根据条件调用任何过程,将结果转储到 #temp 表中,然后在与基表的连接中定义其余的选择列表。前期工作更多,但避免了维护问题,并允许您针对每个搜索条件优化存储过程。