【发布时间】: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 语法适用于一次连接两个表的链,这里我们实际上有三个表,一次全部涉及连接条件——从性能的角度来看,它不是明确的赢家也是。