我有这个大代码,我想在搜索中找到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;
如果我的搜索不是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个搜索条件,我想知道是否可以使用case,decode甚至是带参数的另一个光标,用以下内容进行内部选择:
- 如果搜索字符串不为空,则为LI;
- 没有LIKE,如果字符串为null;
但我没有看到任何这方面的例子,事情真的会变得非常混乱。 有人可以用相同的代码帮助新手吗?
答案 0 :(得分: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 :(得分: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 :(得分:1)
感谢您的回复,我发现它们非常有趣,而且我的代码变得更清晰,更具可读性。尽管如此,OMG小马似乎比另一个更好。但我发现我的代码仍然很大,也许我很顽固!
这是最终结果,可能感兴趣的人
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;