1

我有这个大代码,我想要在搜索中做 3 件事:
1- 查找与搜索匹配的所有订单(已交付和未交付):
2- 查找与搜索匹配的所有待处理订单;
3-查找与搜索匹配的所有已交付订单;

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)to-->(select f1.id_fornecedor from fornecedor f1)and f.data_entrega is not null)

所以我有 3 个搜索条件,我想知道是否可以使用 case、decode 甚至另一个带参数的游标来执行此内部选择:
- LIKE 如果搜索字符串不为空;
- 如果字符串为空,则没有 LIKE;

但是我还没有看到任何这样的例子,事情真的会变得非常混乱。有人可以用相同的代码帮助新手吗?

4

3 回答 3

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;
/
于 2010-01-24T08:22:05.900 回答
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了过程中的子句。

于 2010-01-24T08:26:54.223 回答
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;
于 2010-01-24T18:01:31.773 回答