[英]What's the most efficient way to check if a record exists in Oracle?
一种)
select decode(count(*), 0, 'N', 'Y') rec_exists
from (select 'X'
from dual
where exists (select 'X'
from sales
where sales_type = 'Accessories'));
二)
select decode(count(*), 0, 'N', 'Y') rec_exists
from (select 'X'
from sales
where sales_type = 'Accessories');
C)其他(具体说明)
编辑:很难选择“正确”的答案,因为最好的方法取决于你在检查值是否存在后想要做什么,正如 APC 所指出的那样。 我最终选择了 RedFilter 的答案,因为我最初将此支票设想为 function 本身。
select case
when exists (select 1
from sales
where sales_type = 'Accessories')
then 'Y'
else 'N'
end as rec_exists
from dual;
您想要实现的基础逻辑是什么? 例如,如果您想测试是否存在记录以确定要插入或更新,那么更好的选择是使用MERGE 。
如果您希望记录大多数时间都存在,那么这可能是最有效的处理方式(尽管CASE WHEN EXISTS解决方案可能同样有效):
begin
select null into dummy
from sales
where sales_type = 'Accessories'
and rownum = 1;
-- do things here when record exists
....
exception
when no_data_found then
-- do things here when record doesn't exists
.....
end;
如果SALES_TYPE不是唯一的,您只需要ROWNUM行。 当你想要知道的是否至少存在一条记录时,进行计数毫无意义。
select count(1) into existence
from sales where sales_type = 'Accessories' and rownum=1;
Oracle计划表示如果索引seles_type列,则成本为1。
如果我们需要选择一个名称以及该名称是否存在,那么您只能检查y,n。
select name , decode(count(name),0, 'N', 'Y')
from table
group by name;
这里当它只是Y时它将返回输出,否则它将始终为null。 如果在输出中得到N不存在的记录,我们将获得Name,N。当表中不存在名称时
select decode(count(*), 0, 'N', 'Y') rec_exists
from sales
where sales_type = 'Accessories';
select NVL ((select 'Y' from dual where exists
(select 1 from sales where sales_type = 'Accessories')),'N') as rec_exists
from dual
1.如果sales_type表中存在记录,则双表将返回'Y'。如果sales_type表中不存在记录,则表将返回null,并且NVL将其转换为'N'
确定行是否存在的最有效和最安全的方法是使用FOR-LOOP ...如果您希望插入行或根据不存在的行执行某些操作,您甚至不会遇到困难时间,如果您需要确定是否存在行,这肯定会对您有所帮助。 详见下面的示例代码......
如果你只想知道你的潜在多重回归集中存在1条记录,那么你可以在第一次击中它之后退出循环。
如果不存在记录,则根本不会输入循环。 如果该行不存在,您将不会收到来自Oracle的任何投诉,但您必须知道它是否无关紧要。 我90%的时间使用它(当然取决于我的需要)......
例:
DECLARE
v_exist varchar2(20);
BEGIN
FOR rec IN
(SELECT LOT, COMPONENT
FROM TABLE
WHERE REF_DES = (SELECT REF_DES FROM TABLE2 WHERE ORDER = '1234')
AND ORDER = '1234')
LOOP
v_exist := "IT_EXISTS"
INSERT INTO EAT_SOME_SOUP_TABLE (LOT, COMPONENT)
VALUES (rec.LOT, rec.COMPONENT);**
--Since I don't want to do this for more than one iteration (just in case there may have been more than one record returned, I will EXIT;
EXIT;
END LOOP;
IF v_exist IS NULL
THEN
--do this
END IF;
END;
- 这是在这里的循环之外上面的IF-CHECK无论如何都会运行,但是你会知道你的变量是否为空或不正确! 如果没有返回记录,它将跳过循环,然后转到下一个代码...如果(在我们的上面的例子中),返回了4条记录,我会在第一次迭代后退出,因为我的EXIT ; ...如果不存在,那么4条记录将遍历并对所有记录进行插入。 或者至少尝试一下。
顺便说一句,我不是说这是你应该考虑这样做的唯一方法......你可以
SELECT COUNT(*) INTO v_counter WHERE ******* etc...
然后检查一下
if v_counter > 0
THEN
--code goes here
END IF;
还有更多方法......只需在需要时确定它。 牢记性能和安全。
select CASE
when exists (SELECT U.USERID,U.USERNAME,U.PASSWORDHASH
FROM TBLUSERS U WHERE U.USERID =U.USERID
AND U.PASSWORDHASH=U.PASSWORDHASH)
then 'OLD PASSWORD EXISTS'
else 'OLD PASSWORD NOT EXISTS'
end as OUTPUT
from DUAL;
另一个解决方案:
我在 SO 中看到了很多解决方案,这些解决方案都很好, count(1) or count(*), when exists, where exists, left join, loop with no data exception..
我更喜欢下面的选项,希望这在大数据中表现良好,虽然没有检查:)
返回 1 或 0 (如果您对数字变量进行检查,则可以使用)
SELECT NVL(MIN(1),0)
FROM SALES
WHERE SALES_TYPE = 'ACCESSORIES' AND ROWNUM = 1
返回 Y 或 N (如果您对字符串变量进行检查,则可以使用)
SELECT DECODE(MIN(1),1, 'Y', 'N')
FROM SALES
WHERE SALES_TYPE = 'ACCESSORIES' AND ROWNUM = 1
有多种选择,请针对您的场景进行性能测试并选择最佳选项。
只需计算您正在寻找的记录。 如果count> 0则存在记录。
DECLARE rec_count NUMBER := 0; BEGIN select count(*) into rec_count from EMPLOYEETABLE WHERE employee_id = inEMPLOYEE_ID AND department_nbr = inDEPARTMENT_NBR; if rec_count > 0 then {UPDATE EMPLOYEETABLE} else {INSERT INTO EMPLOYEETABLE} end if; END;
SELECT 'Y' REC_EXISTS
FROM SALES
WHERE SALES_TYPE = 'Accessories'
结果将为'Y'或NULL。 只需测试'Y'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.