检查表[pl / sql block]中是否存在行的正确方法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了检查表[pl / sql block]中是否存在行的正确方法相关的知识,希望对你有一定的参考价值。
昨天我正在编写一些任务,让我感到震惊的是,当我使用pl / sql时,我并不知道检查表中是否存在行的正确和接受方式。
例如,让我们使用表格
PERSON(ID, Name);
显然我做不到(除非有一些秘密方法)类似于:
BEGIN
IF EXISTS SELECT id FROM person WHERE ID = 10;
-- do things when exists
ELSE
-- do things when doesn't exist
END IF;
END;
所以我解决它的标准方法是:
DECLARE
tmp NUMBER;
BEGIN
SELECT id INTO tmp FROM person WHERE id = 10;
--do things when record exists
EXCEPTION
WHEN no_data_found THEN
--do things when record doesn't exist
END;
但是我不知道它是否被接受的方式,或者如果有更好的检查方法,如果有人可以与我分享他们的智慧,我真的会感到高兴:)
干杯。
我不会将常规代码推送到异常块中。只需检查是否存在符合条件的行,然后从那里继续:
declare
any_rows_found number;
begin
select count(*)
into any_rows_found
from my_table
where rownum = 1 and
... other conditions ...
if any_rows_found = 1 then
...
else
...
end if;
带有独立SELECT的IMO代码,用于检查表中是否存在行,但没有充分利用数据库。在你的例子中,你有一个硬编码的ID值,但这不是应用程序在“现实世界”中工作的方式(至少在我的世界中不是 - 你的可能会有所不同:-)。在典型的应用程序中,您将使用光标查找数据 - 所以假设您有一个正在查看发票数据的应用程序,并且需要知道客户是否存在。应用程序的主体可能是这样的
FOR aRow IN (SELECT * FROM INVOICES WHERE DUE_DATE < TRUNC(SYSDATE)-60)
LOOP
-- do something here
END LOOP;
并且在-- do something here
中,您想要查找客户是否存在,如果没有打印错误消息。
一种方法是插入某种单例SELECT,如
-- Check to see if the customer exists in PERSON
BEGIN
SELECT 'TRUE'
INTO strCustomer_exists
FROM PERSON
WHERE PERSON_ID = aRow.CUSTOMER_ID;
EXCEPTION
WHEN NO_DATA_FOUND THEN
strCustomer_exists := 'FALSE';
END;
IF strCustomer_exists = 'FALSE' THEN
DBMS_OUTPUT.PUT_LINE('Customer does not exist!');
END IF;
但IMO相对缓慢且容易出错。 IMO更好的方式(tm)这样做是将它合并到主光标中:
FOR aRow IN (SELECT i.*, p.ID AS PERSON_ID
FROM INVOICES i
LEFT OUTER JOIN PERSON p
ON (p.ID = i.CUSTOMER_PERSON_ID)
WHERE DUE_DATA < TRUNC(SYSDATE)-60)
LOOP
-- Check to see if the customer exists in PERSON
IF aRow.PERSON_ID IS NULL THEN
DBMS_OUTPUT.PUT_LINE('Customer does not exist!');
END IF;
END LOOP;
此代码依据PERSON.ID被声明为PERSON上的PRIMARY KEY(或至少为NOT NULL);逻辑是,如果PERSON表外部连接到查询,并且PERSON_ID出现为NULL,则意味着在PERSON中找不到给定CUSTOMER_ID的行,因为PERSON.ID必须具有值(即至少为NOT空值)。
分享和享受。
许多方法皮肤这只猫。我在每个表的包中放了一个简单的函数......
function exists( id_in in yourTable.id%type ) return boolean is
res boolean := false;
begin
for c1 in ( select 1 from yourTable where id = id_in and rownum = 1 ) loop
res := true;
exit; -- only care about one record, so exit.
end loop;
return( res );
end exists;
让你的支票真的很干净......
IF pkg.exists(someId) THEN
...
ELSE
...
END IF;
select nvl(max(1), 0) from mytable;
如果没有行,则此语句产生0;如果该表中至少有一行,则该语句产生1。它比选择计数(*)更快。优化器“看到”只需要获取一行来回答问题。
这是一个(冗长)小例子:
declare
YES constant signtype := 1;
NO constant signtype := 0;
v_table_has_rows signtype;
begin
select nvl(max(YES), NO)
into v_table_has_rows
from mytable -- where ...
;
if v_table_has_rows = YES then
DBMS_OUTPUT.PUT_LINE ('mytable has at least one row');
end if;
end;
Select 'YOU WILL SEE ME' as ANSWER from dual
where exists (select 1 from dual where 1 = 1);
Select 'YOU CAN NOT SEE ME' as ANSWER from dual
where exists (select 1 from dual where 1 = 0);
Select 'YOU WILL SEE ME, TOO' as ANSWER from dual
where not exists (select 1 from dual where 1 = 0);
如果使用显式游标,则应如下所示。
DECLARE
CURSOR get_id IS
SELECT id
FROM person
WHERE id = 10;
id_value_ person.id%ROWTYPE;
BEGIN
OPEN get_id;
FETCH get_id INTO id_value_;
IF (get_id%FOUND) THEN
DBMS_OUTPUT.PUT_LINE('Record Found.');
ELSE
DBMS_OUTPUT.PUT_LINE('Record Not Found.');
END IF;
CLOSE get_id;
EXCEPTION
WHEN no_data_found THEN
--do things when record doesn't exist
END;
select max( 1 )
into my_if_has_data
from MY_TABLE X
where X.my_field = my_condition
and rownum = 1;
不迭代所有记录。
如果MY_TABLE没有数据,则my_if_has_data设置为null。
以上是关于检查表[pl / sql block]中是否存在行的正确方法的主要内容,如果未能解决你的问题,请参考以下文章
检查架构中的 IF 表 EXISTS 时发生 Oracle PL/SQL 过程错误 [重复]