繁体   English   中英

检查 Oracle 中是否存在记录的最有效方法是什么?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM