存储过程中的Oracle条件WHERE

9q78igpj  于 2023-10-16  发布在  Oracle
关注(0)|答案(4)|浏览(155)

我想编写一个存储过程来选择载体,并使用一个附加参数'i_showEmptyCarrier'来指定是否需要隐藏或显示空载体。

+---------------------------+
|          Carriers         |
+----+----------+-----------+
| id | label    | location  |
+----+----------+-----------+
| 1  | carrier1 | warehouse |
+----+----------+-----------+
| 2  | carrier2 | warehouse |
+----+----------+-----------+
| 3  | carrier3 | factory   |
+----+----------+-----------+

我需要查询“产品”表来检查承运人是否为空。

+-------------------------------------------+
|                  products                 |
+----+-----------+----------------+---------+
| id | carrierid | productiondate | deleted |
+----+-----------+----------------+---------+
| 1  | 1         | 09/09/2020     | 1       |
+----+-----------+----------------+---------+
| 2  | 1         | 09/09/2020     | 0       |
+----+-----------+----------------+---------+
| 3  | 1         | 09/09/2020     | 0       |
+----+-----------+----------------+---------+
| 4  | 2         | 10/09/2020     | 0       |
+----+-----------+----------------+---------+
| 5  | 2         | 10/09/2020     | 0       |
+----+-----------+----------------+---------+

因此,在这种情况下,载体3是空的。
我想要的存储过程逻辑是:

PROCEDURE GetCarriers
(
    i_showEmptyCarrier IN number,
    c_Carriers OUT t_cursor
)
AS
BEGIN
OPEN c_Carriers FOR 
SELECT 
label,
(   select count(*) 
    from products 
    where products.carrierid = carriers.carrierid
    and records.deleted = 0
) as nrOfProducts
FROM carriers
if(i_showEmptyCarrier == 1) {
//select carriers without a product
WHERE nrOfProducts = 0 ;
}
else{
//select carriers with a product
WHERE nrOfProducts > 0 ;
}
END GetCarriers;

因此,如果“i_showEmptyCarrier”= 1,则将选择空载波3号,

+----------+--------------+
| label    | nrOfProducts |
+----------+--------------+
| carrier3 | 0            |
+----------+--------------+

否则仅选择载波1和2。

+----------+--------------+
| label    | nrOfProducts |
+----------+--------------+
| carrier1 | 2            |
+----------+--------------+
| carrier2 | 2            |
+----------+--------------+
t30tvxxf

t30tvxxf1#

如何修改查询以使用left joinconditional aggregation,最后比较输入,

SELECT label,nrOfProducts
FROM
(
  SELECT c.label,SUM(CASE WHEN p.deleted = 0 THEN 1 ELSE 0 END) nrOfProducts
   FROM carriers c
  LEFT JOIN products p 
  ON p.carrierid = c.id
  GROUP BY c.label
)
WHERE ((&i_showEmptyCarrier = 1 AND nrOfProducts = 0) 
       OR (&i_showEmptyCarrier = 0 AND nrOfProducts > 0));
  • 您仍然可以使用where子句进行查询,而不是使用if-else。*
af7jpaap

af7jpaap2#

在一种情况下需要一个内部联接,在另一种情况下需要一个外部联接。因为外部联接仅仅意味着外部联接行的所有列都为空,但是,在这两种情况下,您都可以简单地进行外部联接,然后再决定是删除还是保留外部联接行。
在SQL中,这很简单:

select *
from carriers c
left join products p on p.carrierid = c.id
where (:show_empty = 'only non-empty' and p.id is not null)
   or (:show_empty = 'only empty' and p.id is null)
   or (:show_empty = 'all')

(And当然,你可以把它聚合成count(p.id)。在这种情况下,您可以选择group by c.id或查看一个载波where c.id = :carrier_id

dphi5xsq

dphi5xsq3#

看起来你有很多Java(或其他编程语言)的影响。我不知道你到底想要什么。但这里是你如何实现你想要的。

create or replace procedure p_get_carriers(pi_carrier_flag in varchar2, po_carriers out t_cursor)
is
    lt_cursor   t_cursor;
begin
    select  *
    bulk collect into lt_cursor
    from    records
    where   deleted = case when pi_carrier_flag = 'Y' then 0 else deleted end;
    po_carriers := lt_cursor;
exception
when others then
    po_carriers := null;
end p_get_carriers;

这意味着你不需要使用if-else块来处理它。您可以在查询本身的where子句中执行此操作。
注意:我不知道你的表结构和集合细节。我猜它和张贴的代码。您可能需要相应地调整它。

xnifntxz

xnifntxz4#

您可以创建一个存储过程,以只显示空载体或不以这种方式使用if语句和游标,你已经尝试过:

CREATE OR REPLACE PROCEDURE p_get_carriers(
    pi_carrier_flag IN VARCHAR2,
    po_carriers OUT SYS_REFCURSOR
)
IS
BEGIN
    IF pi_carrier_flag = 'Y' THEN
        OPEN po_carriers FOR
        SELECT DISTINCT c.id, c.label, c.location
        FROM carriers c
        LEFT JOIN products p ON c.id = p.carrierid
        WHERE p.deleted = 0 OR p.deleted IS NOT NULL;
     ELSE
        OPEN po_carriers FOR
        SELECT c.id, c.label, c.location
        FROM carriers c
        LEFT JOIN products p ON c.id = p.carrierid
        WHERE p.deleted IS NULL;
    END IF;
EXCEPTION
    WHEN OTHERS THEN
        NULL;
END p_get_carriers;
/

通过这种方式,您可以调用存储过程

set serveroutput on
    DECLARE
        v_carrier_flag VARCHAR2(1) := 'N'; -- You can set 'Y' or 'N' as needed
        v_cursor SYS_REFCURSOR;
        carrier_id NUMBER;
        carrier_label VARCHAR2(15);
        carrier_location VARCHAR2(15);
    BEGIN
   
 p_get_carriers(v_carrier_flag, v_cursor);

    LOOP
        FETCH v_cursor INTO carrier_id, carrier_label, carrier_location;
        EXIT WHEN v_cursor%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE('Carrier ID: ' || carrier_id);
        DBMS_OUTPUT.PUT_LINE('Carrier Label: ' || carrier_label);
        DBMS_OUTPUT.PUT_LINE('Carrier Location: ' || carrier_location);
    END LOOP;
    CLOSE v_cursor;
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('An error occurred: ' || SQLERRM);
END;
/

希望它能帮助

相关问题