检查行是否存在的最快方法

时间:2014-11-14 14:24:23

标签: sql oracle plsql

select SOMETHING into v_something之前,我想知道我的查询是否返回一行。

这是一个很好的方法,但如果行存在,则花费两个select

select count(1) into isRowExists from PERSON where CONDITION='Something';

if (isRowExists > 0) then
    select NAME into v_name from PERSON where CONDITION='Something';
else
    raise name_not_found;
end if;

select count(1) into isRowExists from CAR where CONDITION='Something';

if (isRowExists > 0) then
    select MODEL into v_model from CAR where CONDITION='Something';
else
    raise model_not_found;
end if;

或类似的东西:

select NAME into v_name from PERSON where CONDITION='Something';

select MODEL into v_model from CAR where CONDITION='Something';

exception
    when no_data_found then
        --do_something

但是使用这种方法,我不知道问题是来自PERSON还是CAR ......

还有其他解决方案吗?比如将参数发送到exception

6 个答案:

答案 0 :(得分:6)

你可以这样做:

BEGIN
    BEGIN
        select NAME into v_name from PERSON where CONDITION='Something';
    exception
        when no_data_found then
        --do_something
    END;

    BEGIN
        select MODEL into v_model from CAR where CONDITION='Something';
    exception
        when no_data_found then
            --do_something
    END;
END;
/

答案 1 :(得分:3)

对于第二种方法,您可以将每个方法包装在begin / end块中:

begin
    select NAME into v_name from PERSON where CONDITION='Something';
exception
    when no_data_found then
        --do_something
end;

begin
    select MODEL into v_model from CAR where CONDITION='Something';

exception
    when no_data_found then
        --do_something
end;

答案 2 :(得分:1)

如果name不为null,您可以尝试:

select (select NAME from PERSON where CONDITION='Something') into v_name 
from dual;

if v_name is null then 
...

我不会说捕捉NO_DATA_FOUND是最快的方法。这真的取决于。有时候执行计数然后获取会更好。 COUNT的工作速度比检索数据的速度快,因此如果行存在的概率很高,则COUNT将更有利。并且Oracle使用一些缓存机制,因此具有相同WHERE的第二个查询将更快地执行。

答案 3 :(得分:1)

避免例外的另一个解决方案:

declare
  client_name varchar2(100);
  model_name varchar2(100);

  cursor clients (p_id number) is
    select client_name from client_table where client_id = p_id;

  cursor models (p_id number) is
    select model_name from model_table where model_id = p_id;

begin
  -- variant 1
  for i in clients(123) loop
    client_name := i.client_name;
    exit;
  end loop;

  -- variant 2
  open models(456);
  fetch models into model_name;

  -- if you need to process "no data found" situation: 
  if models%notfound then
     <do something>
  end;
end;

答案 4 :(得分:-1)

MERGE

This answer为Oracle提供了一个示例。


INSERT WHERE NOT EXISTS

我不确定这可以在Oracle中运行,我相信它适用于一般的SQL RDBMS,如MySQL和PostgreSQL。

INSERT INTO v_name(name) 
   SELECT name FROM person 
   WHERE NOT EXISTS (
      SELECT 1 FROM person WHERE <name/condition> = <value>
   ); 

-- UPDATE ...; -- Add UPDATE statement here to complete an UPSERT query

请表达downvotes的原因:)

答案 5 :(得分:-2)

您可以参数化查询,这将花费您1次选择查询,如

@tablename varchar,
@conditionparameter varchar,

select count(1) into isRowExists from tablename where CONDITION='+conditionparameter+' ;
if(@tablename ='PERSON ' and isRowExists > 0)

select NAME into v_name from PERSON where CONDITION='Something';

elseif (@tablename ='CAR' and isRowExists > 0)

select MODEL into v_model from CAR where CONDITION='Something';

else
raise name_not_found;
end if;

这是一般概念,您可以进一步优化上述查询。