2010-01-24 5 views
1

의 Ref 커서의 내부 케이스 또는 디코딩 : 검색과 일치
1 모든 주문에 대한보기 (전달되지 않음) :
2 - 검색과 일치하는 모든 펜던트 주문을 찾습니다.
3 검색과 일치하는 모든 배달 된 주문을 찾습니다.-경우 다른 내가 내 검색 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; 

내 검색 null가 아닌 경우,이 작동하지만,이 경우 나는 조금에게 내부 선택을 수정하고이 같은으로 바꿀 싶습니다 : (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 없는;
- LIKE이 없으면 문자열이 null 인 경우;

그러나 이것에 대한 예는 보지 못했지만 실제로는 상당히 엉망이 될 수 있습니다. 누군가가 동일한 코드로 초보자를 도울 수 있습니까?

답변

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

관련 문제