【问题标题】:Static SQL conditional WHERE clause from a Function来自函数的静态 SQL 条件 WHERE 子句
【发布时间】:2021-12-11 05:22:17
【问题描述】:

说我有以下功能:

function xx_func 
return varchar2
is

    l_value varchar2(1);

begin

    select  'Y'
    into    l_value
    from    func_table
    where   lookup = 'hello';
    
    RETURN l_value;
    
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        l_value := 'N';
        RETURN l_value;
end xx_func;

现在,在当前的 PL/SQL 代码中,我们有:

DECLARE

    l_optin varchar2(100);
    t_col1  varchar2(100);

BEGIN

    l_optin := xx_func;
    
    if l_optin = 'Y' then
    
        select  col1
        into    t_col1
        from    xx_table_1 xx1
            ,   xx_table_2 xx2
        where   1=1
        and     xx1.t_col2 = xx2.t_col2;
        
    else

        select  col1
        into    t_col1
        from    xx_table_1 xx1
            ,   xx_table_2 xx2
        where   1=1
        and     xx1.t_col2 = xx2.t_col2
        and     xx1.t_col3 = xx2.t_col3;
        
    end if;
    
END;

我想这样编码以使其更短:

DECLARE

    l_optin varchar2(100);
    t_col1  varchar2(100);

BEGIN

    l_optin := xx_func;
    
    select  col1
    into    t_col1
    from    xx_table_1 xx1
        ,   xx_table_2 xx2
    where   1=1
    and     xx1.t_col2 = xx2.t_col2 
    and     ((xx1.t_col3 = xx2.t_col3 and l_optin = 'N')
    OR       (l_optin = 'Y'));
            
END;    

上面的代码告诉我If l_optin is 'N' 然后evaluate xx1.t_col3 = xx2.t_col3. if l_optin = 'Y',然后不要评估xx1.t_col3 = xx2.t_col3. 我尝试在本地对其进行测试并且它可以工作,但我的同事说它不适用于所有场景。列不能为空。

是否有任何可能无法处理的情况?

注意:

  • 我们不能使用动态 SQL
  • 此示例代码在超过14000的包中出现多次 行,因此,在这一点上很难阅读。

【问题讨论】:

  • 在我看来,由于您不需要按输入的字符数收费,因此请使用更易于遵循和维护的选项。您发布的第一个代码很简单 - 如果函数返回 Y,则执行 this;否则,请那个。您的第二个代码看起来更智能,但是 - 它更有效吗?想象有人继承了你的代码。想象你自己继承a)简单代码,b)复杂代码。你更喜欢哪一个?我并不是说这个例子是那个复杂的。只是我更喜欢简单。
  • 向您的同事询问它不起作用的情况,因为就我而言,没有任何情况(至少也没有对原始查询不起作用。如果如果您想让代码更短,我质疑将 1=1 用作 WHERE 子句的一部分,AFAIK 只有在您已经在使用动态 SQL 并且需要确保附加到有效的 where 子句时才有用。跨度>
  • 另外,如果我们谈论的是风格和可读性,第二个版本中的OR 是错误的,大小写不一致。
  • @Littlefoot 当有人必须来清理逗号连接时,他们更愿意编辑一两个查询吗? :)
  • 我同意康纳的观点。我已经开始写答案,推荐使用 ANSI 连接并将xx_func 函数的逻辑分解为单个 SQL(即... from xx_table_1 xx1 join xx_table_2 xx2 on xx1.t_col2 = xx2.t_col2 left join func_table ft on ft.lookup = 'hello' where (ft.lookup is not null or xx1.t_col3 = xx2.t_col3))。无论如何,我最终认为它的可读性是有争议的——ANSI 语法适用于一次连接两个表的链,这里我们实际上有三个表,一次全部涉及连接条件——从性能的角度来看,它不是明确的赢家也是。

标签: sql oracle plsql


【解决方案1】:

对于每个主张根据要求使用 SQL 语句(即上面的 2 条语句)的人,都会有人主张从单个 SQL 中获得尽可能多的“物有所值”(上面的 1 条语句),所以我不会试图告诉你是对是错。

我的 preference 通常是多条语句,因为我给优化器提供了一个好的计划的最佳机会,但没有规则,因为 2 条语句可能很好,但 200 条听起来像我'做得太过分了等等。

同样,这两者并不是相互排斥的——我见过可能存在多种排列的代码,因此最常见的用法是用静态 SQL 编码的,其中“fallthrough”选项是为罕见排列动态构建的 SQL。

您选择 喜欢的东西,同时满足可维护性的目标并为优化器保持简单。

虽然我假设您的示例是伪代码,但以防它们确实代表您的真实代码

  • 您不需要“where 1=1”
  • 如果“col2”连接产生单行,“col2/col3”配对如何产生不同的结果?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-16
    相关资源
    最近更新 更多