如何订购动态选择

时间:2017-08-11 11:57:08

标签: java oracle

我在oracle中有这样的功能

FUNCTION myFunc(p_order_col    IN VARCHAR2 default 'city')
RETURN SYS_REFCURSOR IS
    v_result          SYS_REFCURSOR;
begin

    open v_result for  select m.abrv_name AS abrv_name,
               m.full_name AS merchant_name,
               m.city AS city,
               m.phone AS phone
    from myTable m
    where m.full_name=SomeCondition
    order by CASE WHEN p_order_col = 'city' then ff.city end,
               CASE WHEN p_order_col = 'abrv_name' then m.abrv_name end,
               CASE WHEN p_order_col = 'phone' then  m.phone end;

    return v_result;

end myFunc;

我正在从java传递p_order_col参数,但我得到了有序数据,即使是通过参数传递参数我也没有得到默认订单数据city param

1 个答案:

答案 0 :(得分:3)

您对可选形式参数的默认值如何工作有点困惑。

如果您将您的功能称为myFunc(),而根本没有参数,则默认值会被应用,并且就像您将其称为myFunc('city')一样。

但是如果你将它称为myFunc(null),这是你的Java调用正在进行的操作,则不使用默认值,p_order_col实际上是空的。

From the documentation

  

带有默认值的形式参数称为可选参数,因为其对应的实际参数在子程序调用中是可选的。

这意味着声明默认值允许在调用中省略参数;所以我上面展示的两个电话都是合法的。

  

省略实际参数不会使相应形式参数的值为NULL。要使形式参数的值为NULL,请将NULL指定为默认值或实际参数。

  

如果子程序调用指定形式参数的实际参数,则该调用不会评估默认值。

一起表示传递null与根本不传递参数不同,并且由于传递null是提供实际参数,因此不使用默认值。

您需要处理显式传递null的可能性;一种方法是在你的第一个order-by子句中合并它:

order by CASE WHEN COALESCE(p_order_col, 'city') = 'city' then ff.city end,
           CASE WHEN p_order_col = 'abrv_name' then m.abrv_name end,
           CASE WHEN p_order_col = 'phone' then  m.phone end;

或者可能更清楚

order by CASE WHEN p_order_col IS NULL OR p_order_col = 'city' then ff.city end,
           CASE WHEN p_order_col = 'abrv_name' then m.abrv_name end,
           CASE WHEN p_order_col = 'phone' then  m.phone end;

如果你确定你实际上没有传递null和/或想要按城市排序,如果传入其他未知值,你可以从另一个角度接近:

order by CASE WHEN p_order_col is null
  or p_order_col not in ('abrv_name', 'phone') then m.city end,

但是如果以后添加更多有效选项,则需要维护该列表。

另一种方法是,如果所有列都是相同的数据类型或可以强制使用,则使用单个案例表达式:

order by CASE p_order_col WHEN 'abrv_name' then m.abrv_name
  WHEN 'phone' then m.phone ELSE m.city end;

else处理明确或默认的城市' value,null或任何意外值。

如果没有要传递的值,可以更改Java代码以调用没有形式参数的函数:

if someVar == null then
{
    callableStmnt = conn.prepareCall("{?=call myFunc()}");
    callableStmnt.registerOutParameter(1, OracleTypes.CURSOR); 
}
else
{
    callableStmnt = conn.prepareCall("{?=call myFunc(?)}");
    callableStmnt.registerOutParameter(1, OracleTypes.CURSOR); 
    callableStmnt.setString(2, someVar);
}
callableStmnt.execute;

但这可能会使其不必要地复杂化,并且无论如何都能更好地正确处理这种情况。