我在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
答案 0 :(得分:3)
您对可选形式参数的默认值如何工作有点困惑。
如果您将您的功能称为myFunc()
,而根本没有参数,则默认值会被应用,并且就像您将其称为myFunc('city')
一样。
但是如果你将它称为myFunc(null)
,这是你的Java调用正在进行的操作,则不使用默认值,p_order_col
实际上是空的。
带有默认值的形式参数称为可选参数,因为其对应的实际参数在子程序调用中是可选的。
这意味着声明默认值允许在调用中省略参数;所以我上面展示的两个电话都是合法的。
省略实际参数不会使相应形式参数的值为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;
但这可能会使其不必要地复杂化,并且无论如何都能更好地正确处理这种情况。