2017-08-11 45 views
0

我有功能在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参数,但我得到有序的数据,甚至withought通过传递参数我没有得到的数据与秩序默认city参数

+0

你能分享一些样本数据和你得到的结果吗?对于远处的代码看起来正确 – Mureinik

+0

当我打电话时没有通过'p_order_col'参数它必须返回与订单城市的数据,但我得到像'Rustavi','第比利斯','第比利斯','Rustavi'等城市PS这是我县的城市 –

+0

你可以给你的Java电话打个招呼吗? –

回答

3

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

如果你在所有的调用函数为myFunc(),不带参数,那么默认的应用,它的作用,如果你想叫它为myFunc('city')

但是,如果您将其称为myFunc(null),这是您的Java调用正在执行的操作,则不会使用默认值,并且p_order_col实际上为null。

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处理的明确或默认的“城市'值,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; 

但是这可能不必要地复杂了,它是为更好函数来正确处理这种情况。

+0

我改变了它,就像你说的'p_order_col IS NULL OR p_order_col ='city''但仍然保存结果我甚至声明新的变量像'v_order_col VARCHAR2(40);'和'IF(p_order_col IS NULL)然后 v_order_col:='city'; ELSE v_order_col:= p_order_col; END IF; '然后我写了'CASE WHEN v_order_col IS NULL OR v_order_col ='city'then ff.city end, CASE WHEN v_order_col ='abrv_name'then m.abrv_name end, CASE WHEN v_order_col ='phone'then m.phone end; '但没有订单仍然是相同的结果数据 –

+0

请不要将大量的代码转储到注释中。这适用于我......在这种情况下,你究竟传递给'setString()'什么? (这就是为什么将Java代码添加到问题中会有帮助的原因)。 –