【问题标题】:Rewriting dynamic SQL in to stored procedure将动态 SQL 重写为存储过程
【发布时间】:2015-01-07 19:34:07
【问题描述】:

我看到之前在 this post 中已经提出了这个问题,并且还查看了 WHEN-THEN 构造,但它确实没有回答一些问题。

目前在代码中使用 StringBuilder 构建 SQL 查询,如下所示:

buildSearchQuery.Append("SELECT * FROM Policy WHERE Field_1 = '" + param_1 + "'");

if (Condition 2){
    buildSearchQuery.Append("AND Field_2 = '" + param_2 + "' ");
}
if (Condition 2)
{
   buildSearchQuery.Append("AND Field_3 = '" + param_3 + "' ");
}
...

你明白了。这些参数值总共有 20 个,我的任务是创建一个存储过程并将这些值作为参数传递。

我是否创建一个包含所有参数的存储过程并在那里执行逻辑,如果是,我不确定如何。像这样?

SELECT * FROM TABLE WHERE Field_1 = @param_1
IF(@param_2 <> NULL)
    AND Field_2 = param_2
...

这些参数并不总是有值,因此它们不能成为查询的一部分。什么是让这项工作牢记性能的最佳方法?

【问题讨论】:

标签: sql sql-server tsql


【解决方案1】:

您的存储过程将有 3 个参数 @param_1、@param_2、@param_3

这些参数的默认值可以设置为NULL。

存储过程里面的条件会是这样的

WHERE  ( @param_1 is NULL or field_1 = @param_1)
       AND 
       ( @param_2 is NULL or field_2 = @param_2)
       AND
       ( @param_3 is NULL or field_3 = @param_3)

OPTOIN(RECOMPILE)

添加OPTION(RECOMPILE) 会在每次执行查询时重新构建执行计划,在OR 条件下这将是有益的。

【讨论】:

  • 我已经尝试过,除了表中的大多数字段都具有not null 约束并抛出错误Procedure or function ... expects parameter '@param_1', which was not supplied.。这是实际代码AND (@State IS NULL OR [State] = @State)
  • @Risho,在存储过程的情况下,您不能跳过 param1 并只给出 param2,您需要将 parma1 作为 NULL 传递,然后传递 param2
  • 我认为这是一个错字。那么问题是如果我将@param_1 传递给不会产生所需记录的field_2,会吗?
  • @Risho,这是一个错字,我的意思是 exec sp NULL,param_2 应该工作或 exec sp(如果都是 NULL)或 exec sp,NULL,NULL,param_3
  • @radar,以这种方式编写的查询通常通过在末尾添加OPTION (RECOMPILE) 受益匪浅。这基本上是根据局部变量的当前运行时值重新编译查询,有效地删除 OR 并允许使用索引
【解决方案2】:

由于这些都是可以为空的参数,您可以在 where 中使用 coalesce 而不是括号内的 OR。我觉得它读起来好一点。

WHERE 合并(@param_1,field_1)

合并(@param_2,field_2)

合并(@param_3,field_3)

【讨论】:

    猜你喜欢
    • 2017-08-22
    • 2019-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-06
    相关资源
    最近更新 更多