Oracle PL\SQL 空输入参数 WHERE 条件

发布于 2024-10-17 09:25:54 字数 267 浏览 2 评论 0原文

截至目前,我正在使用 IF ELSE 来处理这种情况,

IF INPUT_PARAM IS NOT NULL

    SELECT ... FROM SOMETABLE WHERE COLUMN = INPUT_PARAM
ELSE
    SELECT ... FROM SOMETABLE

有没有更好的方法可以在没有 IF ELSE 循环的单个查询中执行此操作。随着查询变得复杂,将会有更多这样的输入参数,并且所需的 IF ELSE 数量会太多。

As of now I am using IF ELSE to handle this condition

IF INPUT_PARAM IS NOT NULL

    SELECT ... FROM SOMETABLE WHERE COLUMN = INPUT_PARAM
ELSE
    SELECT ... FROM SOMETABLE

Is there any better way to do this in a single query without IF ELSE loops. As the query gets complex there will be more input parameters like this and the amount of IF ELSE required would be too much.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凉世弥音 2024-10-24 09:25:54

一种方法是使用

 WHERE column = nvl(var, column)

There's 的变体,但是这里有两个陷阱:

  1. 如果列可为空,则此子句将过滤空值,而在您的问题中,在第二种情况下您不会过滤空值。您可以修改此子句以将空值考虑在内,但它会变得很难看:

     WHERE nvl(列, 不可能的值) = nvl(var, 不可能的值)
    

    当然,如果以某种方式插入了impossible_value,您将遇到其他类型的(有趣)问题。

  2. 优化器无法正确理解此类子句。它有时会生成一个包含 UNION ALL 的计划,但如果有多个 nvl,即使存在完全有效的索引,您也会得到完整扫描。

这就是为什么当有很多参数时(例如大表单中的多个搜索字段),我喜欢使用动态 SQL:

DECLARE
   l_query VARCHAR2(32767) := 'SELECT ... JOIN ... WHERE 1 = 1';
BEGIN
   IF param1 IS NOT NULL THEN
      l_query := l_query || ' AND column1 = :p1';
   ELSE 
      l_query := l_query || ' AND :p1 IS NULL';
   END IF;
   /* repeat for each parameter */
   ...
   /* open the cursor dynamically */
   OPEN your_ref_cursor FOR l_query USING param1 /*,param2...*/; 
END;

您还可以使用 EXECUTE IMMEDIATE l_query INTO l_result USING param1;

One method would be to use a variant of

 WHERE column = nvl(var, column)

There are two pitfalls here however:

  1. if the column is nullable, this clause will filter null values whereas in your question you would not filter the null values in the second case. You could modify this clause to take nulls into account but it turns ugly:

        WHERE nvl(column, impossible_value) = nvl(var, impossible_value)
    

    Of course if somehow the impossible_value is ever inserted you will run into some other kind of (fun) problems.

  2. The optimizer doesn't understand correctly this type of clause. It will sometimes produce a plan with a UNION ALL but if there are more than a couple of nvl, you will get full scan even if perfectly valid indexes are present.

This is why when there are lots of parameters (several search fields in a big form for example), I like to use dynamic SQL:

DECLARE
   l_query VARCHAR2(32767) := 'SELECT ... JOIN ... WHERE 1 = 1';
BEGIN
   IF param1 IS NOT NULL THEN
      l_query := l_query || ' AND column1 = :p1';
   ELSE 
      l_query := l_query || ' AND :p1 IS NULL';
   END IF;
   /* repeat for each parameter */
   ...
   /* open the cursor dynamically */
   OPEN your_ref_cursor FOR l_query USING param1 /*,param2...*/; 
END;

You can also use EXECUTE IMMEDIATE l_query INTO l_result USING param1;

↘人皮目录ツ 2024-10-24 09:25:54

这应该有效

SELECT ... FROM SOMETABLE WHERE COLUMN = NVL( INPUT_PARAM, COLUMN )

This should work

SELECT ... FROM SOMETABLE WHERE COLUMN = NVL( INPUT_PARAM, COLUMN )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文