2010-01-24 41 views
1

我有这样大的代码,我想在我的搜索3件事情内侧箱或解码:
1 - 寻找所有的订单(交付,而不是)搜索匹配的:
2-寻找与搜索相匹配的所有吊坠订单;
3-查找与搜索匹配的所有交付订单;的if-else,一个裁判光标

create or replace 
function search_order(search IN VARCHAR2, a_option NUMBER) RETURN types.ref_cursor 
AS 
    orders_cursor types.ref_cursor; 

BEGIN 
    if search is not null then 
     if a_option = 0 then /*case 1*/ 
     OPEN orders_cursor FOR 
      select value(f), value(p),i.qtd_if, i.prec_total_if , forn.nome_fornecedor 
       from item_fornecimento i, produto p ,fornecimento f, fornecedor forn 
       where f.id_fornecimento in (select f.id_fornecimento from fornecimento f where f.id_fornecedor in 
      (select f1.id_fornecedor from fornecedor f1 where f1.nome_fornecedor LIKE '%'||search||'%')) 
       and f.id_fornecimento= i.id_fornecimento and i.id_prod= p.id_prod and 
       f.id_fornecedor = forn.id_fornecedor 
       order by forn.nome_fornecedor,f.data_encomenda desc,p.nome_prod asc; 
     RETURN orders_cursor; 


     ELSIF a_option = 1 then /*case 2*/ 
     OPEN orders_cursor FOR 
     (...) 
      where f.id_fornecimento in (select f.id_fornecimento from fornecimento f where f.id_fornecedor in 
      (select f1.id_fornecedor from fornecedor f1 where f1.nome_fornecedor LIKE '%'||search||'%')and f.data_entrega is null) 
      (...) 
     RETURN orders_cursor; 

     ELSE /* case 3*/ 
     OPEN orders_cursor FOR 
      (...) 
       where f.id_fornecimento in (select f.id_fornecimento from fornecimento f where f.id_fornecedor in 
       (select f1.id_fornecedor from fornecedor f1 where f1.nome_fornecedor LIKE '%'||search||'%')and f.data_entrega is not null) 
       (...) 
      RETURN orders_cursor;  
     end if; 
    end if; 

END; 

这工作,如果我的搜索不为空,但如果是我想只是修改一点点内部的选择,并把它变成是这样的: (select f1.id_fornecedor from fornecedor f1 where f1.nome_fornecedor LIKE '%'||search||'%')and f.data_entrega is not null)到 - >(select f1.id_fornecedor from fornecedor f1)and f.data_entrega is not null)

所以我有3个搜索条件,我想知道是否有可能使用大小写,解码或其他光标与参数,做这个内部选择:
- LIKE如果搜索字符串不是空值;
- 没有LIKE,如果字符串为空;

但我还没有看到任何这样的例子,事情可以真的很乱。 有人可以用相同的代码来帮助新手吗?

回答

2

我也将使用动态SQL,但你可以使用PLSQL情况下,控制执行流程:

BEGIN 

    CASE 
    WHEN search IS NOT NULL AND a_option = 0 THEN 
     OPEN orders_cursor FOR 
     SELECT VALUE(f), 
       VALUE(p), 
       i.qtd_if, 
       i.prec_total_if, 
       forn.nome_fornecedor 
      FROM ITEM_FORNECIMENTO i 
      JOIN PRODUTO p ON p.id_prod = i.id_prod 
      JOIN FORNECIMENTO f ON f.id_fornecimento = i.id_fornecimento 
      JOIN FORNECEDOR forn ON forn.id_fornecedor = f.id_fornecedor 
           AND forn.nome_fornecedor LIKE '%'||search||'%' 
     ORDER BY forn.nome_fornecedor,f.data_encomenda desc,p.nome_prod; 

    WHEN search IS NULL AND a_option = 1 THEN 
     OPEN orders_cursor FOR 
     SELECT VALUE(f), 
       VALUE(p), 
       i.qtd_if, 
       i.prec_total_if, 
       forn.nome_fornecedor 
      FROM ITEM_FORNECIMENTO i 
      JOIN PRODUTO p ON p.id_prod = i.id_prod 
      JOIN FORNECIMENTO f ON f.id_fornecimento = i.id_fornecimento 
          AND f.data_entrega IS NULL 
      JOIN FORNECEDOR forn ON forn.id_fornecedor = f.id_fornecedor 
     ORDER BY forn.nome_fornecedor,f.data_encomenda desc,p.nome_prod; 

    WHEN search IS NOT NULL AND a_option = 1 THEN 
     OPEN orders_cursor FOR 
     SELECT VALUE(f), 
       VALUE(p), 
       i.qtd_if, 
       i.prec_total_if, 
       forn.nome_fornecedor 
      FROM ITEM_FORNECIMENTO i 
      JOIN PRODUTO p ON p.id_prod = i.id_prod 
      JOIN FORNECIMENTO f ON f.id_fornecimento = i.id_fornecimento 
          AND f.data_entrega IS NULL 
      JOIN FORNECEDOR forn ON forn.id_fornecedor = f.id_fornecedor 
           AND forn.nome_fornecedor LIKE '%'||search||'%' 
     ORDER BY forn.nome_fornecedor,f.data_encomenda desc,p.nome_prod; 
    END CASE; 

END; 

这不是完整的,但你的想法。我还将ANSI-89 JOIN语法转换为ANSI-92,并在此过程中删除了IN子句。

2

您可以使用动态SQL来自定义执行的语句。

以下示例根据传递给函数的两个参数返回一组DEPT记录。内部逻辑改变where子句既不使用,也不使用这两个参数。

create or replace function get_dept_details 
    (p_loc dept.location%type := null 
     , p_name dept.dname%type := null) 
    return sys_refcursor 
is 
    rc sys_refcursor; 
    stmt varchar2(32767); 
begin 
    stmt := 'select * from dept'; 
    if p_loc is null and p_name is null 
    then 
     open rc for stmt; 
    elsif p_loc is not null and p_name is null 
    then 
     stmt := stmt||' where loc = :1'; 
     open rc for stmt using p_loc; 
    elsif p_loc is null and p_name is not null 
    then 
     stmt := stmt||' where dname = :1'; 
     open rc for stmt using p_name; 
    else 
     stmt := stmt||' where loc = :1 and dname = :2'; 
     open rc for stmt using p_loc, p_name; 
    end if; 
    return rc; 
end; 
/
1

感谢您的回复,我发现它们非常引人注目,我的代码变得更干净,更具可读性。尽管如此,OMG Ponies似乎比另一个更适合。但是我发现我的代码仍然很大,也许我很固执!

下面是最终的结果,谁可能会感兴趣

create or replace 
function search_order(search IN VARCHAR2, a_option NUMBER) RETURN types.ref_cursor 
AS 
    orders_cursor types.ref_cursor; 

BEGIN 
     CASE  
     /*all the orders that match, no matter if they're delivered or not*/ 
     WHEN search IS NOT NULL AND a_option = 0 THEN 
     OPEN orders_cursor FOR 
     SELECT VALUE(f), 
       VALUE(p), 
       i.qtd_if, 
       i.prec_total_if, 
       forn.nome_fornecedor 
      FROM ITEM_FORNECIMENTO i 
      JOIN PRODUTO p ON p.id_prod = i.id_prod 
      JOIN FORNECIMENTO f ON f.id_fornecimento = i.id_fornecimento 
      JOIN FORNECEDOR forn ON forn.id_fornecedor = f.id_fornecedor 
      AND forn.nome_fornecedor LIKE '%'||search||'%' 
     ORDER BY forn.nome_fornecedor,f.data_encomenda desc,p.nome_prod; 
     RETURN orders_cursor; 

     /*all the orders, no matter if they're delivered or not*/ 
     WHEN search IS NULL AND a_option = 0 THEN 
     OPEN orders_cursor FOR 
     SELECT VALUE(f), 
       VALUE(p), 
       i.qtd_if, 
       i.prec_total_if, 
       forn.nome_fornecedor 
      FROM ITEM_FORNECIMENTO i 
      JOIN PRODUTO p ON p.id_prod = i.id_prod 
      JOIN FORNECIMENTO f ON f.id_fornecimento = i.id_fornecimento 
      JOIN FORNECEDOR forn ON forn.id_fornecedor = f.id_fornecedor 
     ORDER BY forn.nome_fornecedor,f.data_encomenda desc,p.nome_prod; 
     RETURN orders_cursor; 

     /*########################## OPTION 1 #################################*/ 

     /*all the matched and pendent orders*/ 
     WHEN search IS NOT NULL AND a_option = 1 THEN 
     OPEN orders_cursor FOR 
     SELECT VALUE(f), 
       VALUE(p), 
       i.qtd_if, 
       i.prec_total_if, 
       forn.nome_fornecedor 
      FROM ITEM_FORNECIMENTO i 
      JOIN PRODUTO p ON p.id_prod = i.id_prod 
      JOIN FORNECIMENTO f ON f.id_fornecimento = i.id_fornecimento 
      JOIN FORNECEDOR forn ON forn.id_fornecedor = f.id_fornecedor 
      AND forn.nome_fornecedor LIKE '%'||search||'%'AND f.data_entrega IS NULL 
     ORDER BY forn.nome_fornecedor,f.data_encomenda desc,p.nome_prod; 
     RETURN orders_cursor; 

     /*all the pendent orders*/ 
     WHEN search IS NULL AND a_option = 1 THEN 
     OPEN orders_cursor FOR 
     SELECT VALUE(f), 
       VALUE(p), 
       i.qtd_if, 
       i.prec_total_if, 
       forn.nome_fornecedor 
      FROM ITEM_FORNECIMENTO i 
      JOIN PRODUTO p ON p.id_prod = i.id_prod 
      JOIN FORNECIMENTO f ON f.id_fornecimento = i.id_fornecimento 
      JOIN FORNECEDOR forn ON forn.id_fornecedor = f.id_fornecedor 
      AND f.data_entrega IS NULL 
     ORDER BY forn.nome_fornecedor,f.data_encomenda desc,p.nome_prod; 
     RETURN orders_cursor; 

     /*########################## OPTION 2 #################################*/ 
     /*all the matched and delivered orders*/ 
     WHEN search IS NOT NULL AND a_option = 2 THEN 
     OPEN orders_cursor FOR 
     SELECT VALUE(f), 
       VALUE(p), 
       i.qtd_if, 
       i.prec_total_if, 
       forn.nome_fornecedor 
      FROM ITEM_FORNECIMENTO i 
      JOIN PRODUTO p ON p.id_prod = i.id_prod 
      JOIN FORNECIMENTO f ON f.id_fornecimento = i.id_fornecimento 
      JOIN FORNECEDOR forn ON forn.id_fornecedor = f.id_fornecedor 
      AND forn.nome_fornecedor LIKE '%'||search||'%'AND f.data_entrega IS NOT NULL 
     ORDER BY forn.nome_fornecedor,f.data_encomenda desc,p.nome_prod; 
     RETURN orders_cursor; 

     /*all the delivered orders*/ 
     WHEN search IS NULL AND a_option = 2 THEN 
     OPEN orders_cursor FOR 
     SELECT VALUE(f), 
       VALUE(p), 
       i.qtd_if, 
       i.prec_total_if, 
       forn.nome_fornecedor 
      FROM ITEM_FORNECIMENTO i 
      JOIN PRODUTO p ON p.id_prod = i.id_prod 
      JOIN FORNECIMENTO f ON f.id_fornecimento = i.id_fornecimento 
      JOIN FORNECEDOR forn ON forn.id_fornecedor = f.id_fornecedor 
      AND f.data_entrega IS NOT NULL 
     ORDER BY forn.nome_fornecedor,f.data_encomenda desc,p.nome_prod; 
     RETURN orders_cursor; 
     end case; 
END; 
+0

你的代码 - 如你所说 - 太大了,因为有很多重复的。避免重复的方法是将查询分解为组件,并使用动态SQL来组装引用游标语句。明确的重复性方法的优点是您可以获得关于依赖性的反馈。但它带来了维护费用。所以这归结于味道的问题。 – APC 2010-01-24 21:57:51