Reputation: 11
I've been a strictly MS SQL consumer, but have been tasked with writing an Oracle stored procedure that compares 2 tables for missing data. I need to write something that will return a 1 if an order is missing. So far I have the following, but it's not even close to working. I've scoured the web with little results. Any help would be greatly appreciated.
CREATE OR REPLACE PROCEDURE SP_PO_CHECK
AS
BEGIN
IF NOT EXISTS ( SELECT PO FROM ORDERS, PO_LIST, WHERE Order_PO = PO; ) THEN RETURN 0; ELSE RETURN 1
END;
Upvotes: 0
Views: 8562
Reputation: 168081
You could use MINUS
:
CREATE PROCEDURE SP_PO_CHECK (
hasSamePOs OUT NUMBER
)
AS
p_rowcount
BEGIN
SELECT COUNT(1)
INTO p_rowcount
FROM (
SELECT PO FROM PO_LIST
MINUS
SELECT PO FROM ORDERS
);
hasSamePOs := CASE WHEN p_rowcount > 0 THEN 0 ELSE 1 END;
END;
/
Or
CREATE PROCEDURE SP_PO_CHECK (
hasSamePOs OUT NUMBER
)
AS
BEGIN
SELECT CASE WHEN EXISTS (
SELECT PO FROM PO_LIST
MINUS
SELECT PO FROM ORDERS
)
THEN 0
ELSE 1
END
INTO hasSamePOs
FROM DUAL;
END;
/
Upvotes: 1
Reputation: 52386
The correct query to identify this situation is:
select count(*)
from po_list p
where not exists (
select 1
from orders o
where o.order_po = p.po)
and rownum = 1;
This will stop the query as soon as a problem po is found, and return wither 0 or 1.
So select that into a variable and return 1 - its value:
create or replace function missing_order
as
missing_po_found integer;
begin
select count(*)
into missing_po_found
from po_list p
where not exists (
select 1
from orders o
where o.order_po = p.po)
and round = 1;
return 1 - missing_o_found;
end;
Not run, so not 100% sure there's not a typo.
Upvotes: 1
Reputation: 2138
First of all it need to be function not procedure.
Then you need to define how you going to check existence in two tables. You can use master table left join to detail table and check that it returns NOT NULL for some mandatory column (I use rowid because it is always not null). Or you can use NOT EXISTS clause.
Then you need to return result into PL_SQL variable using INTO clause And finally return variable as result of function.
CREATE OR REPLACE FUNCTION SP_PO_CHECK
RETURN NUMBER
AS
l_total_cnt number;
l_match_cnt number;
BEGIN
select count(*), -- total count of record only in po_list. I assume that this is your drive table. If not you can switch tables or use full outer join
count(orders.rowid) -- count of records exist in both tables
into l_total_cnt, l_match_cnt
from po_list
left join orders
on Order_PO = PO;
if l_total_cnt = l_match_cnt then
return 1;
else
return 0;
end if;
END SP_PO_CHECK;
Upvotes: 1
Reputation: 104
Try something like this:
RETURN CASE WHEN (SELECT COUNT(*) FROM ORDERS, PO_LIST, WHERE Order_PO = PO; ) <> (SELECT COUNT(*) FROM ORDERS) THEN 0 ELSE 1 END
Upvotes: 1