如果条件PLSQL返回了错误的值

时间:2014-02-25 14:18:34

标签: if-statement plsql cursor compare

在下面的PLSQL函数中,如果不存在“通知方”,我想返回“客户”值。

结果总是返回条件的值“CUSTOMER即使存在”通知方“。为什么? 我使用了同样的功能但involved_party_qual_gid in ('CONSIGNEE', 'CUSTOMER') 它可以很好地产生所需的结果。

function getNotifyPartyOrCustomer(orderID varchar2) return varchar2

is
NameResult varchar2(100);

CURSOR c_involved_party is
  select involved_party_contact_gid, involved_party_qual_gid
    from order_release_inv_party
   where involved_party_qual_gid in ('NOTIFY PARTY', 'CUSTOMER')
     and order_release_gid = orderID;
begin

for i in c_involved_party loop

  if i.involved_party_qual_gid = 'NOTIFY PARTY' then
    NameResult := i.involved_party_contact_gid;
    return(NameResult);

  elsif i.involved_party_qual_gid = 'CUSTOMER' then
    NameResult := i.involved_party_contact_gid;
    return(NameResult);
  end if;
 end loop;

end;

我已经编写了另外两个产生相同结果的函数:

1-功能1

function getNotifyPartyOrCustomer(orderID varchar2) return varchar2

 is
  NameResult varchar2(100);

 begin

   select coalesce((select involved_party_contact_gid
                  from order_release_inv_party
                 where involved_party_qual_gid = 'NOTIFY PARTY'
                   and order_release_gid = orderID),

                (select involved_party_contact_gid
                   from order_release_inv_party
                  where involved_party_qual_gid = 'CUSTOMER'
                    and order_release_gid = orderID), 

                'NO DATA'

                ) AS NAME
   INTO NameResult

   from DUAL;

  return NameResult;
end;

2-功能2

function getNotifyPartyOrCustomer(orderID varchar2) return varchar2

 is
   NameResult varchar2(100);


 begin

    select involved_party_contact_gid
    INTO NameResult
    from order_release_inv_party
   where involved_party_qual_gid in ('NOTIFY PARTY')
     and order_release_gid = orderID;

   return(NameResult);

     exception WHEN NO_DATA_FOUND THEN

      select involved_party_contact_gid
        into NameResult
        from order_release_inv_party
       where involved_party_qual_gid in ('CUSTOMER')
         and order_release_gid = orderID;   



 return(NameResult);
end;

但是我对这两个函数不满意,因为首先,性能方面,我没有看到必须从同一个表中检索两次,我只能在一次检索中得到结果并执行我的操作对它的逻辑,第二,因为我需要其他逻辑的if条件。

我只需要知道它为什么不起作用。

感谢所有帮助。谢谢。

2 个答案:

答案 0 :(得分:1)

第一个函数的结果将取决于查询返回行的顺序。由于您没有提供order by子句,因此数据库可以按任何顺序返回行。如果您想要将“NOTIFY PARTY”优先于“CUSTOMER”,您可以在查询中添加以下内容:

order by involved_party_qual_gid desc

你可以接受的其他功能可能是巧合。如果某些东西导致数据库以不同的顺序返回行(例如从备份中恢复,重新组织索引,甚至表中的足够数据来更改计划),它可能会发生变化。


<强>后续

通常,当您处理SQL时,如果您在结果集上进行迭代,那么您采取的方法很糟糕。数据库引擎非常擅长处理基于集合的问题,因此通常最好让引擎尽可能多地处理工作。

在这种情况下,看起来你并不真正关心每一行的结果:你真的只想要包含“NOTIFY PARTY”的第一行,如果不存在这样的记录,你想要的第一行是包含“CUSTOMER”。假设您的结果集返回500行。当你只关心1行的值时,为什么要迭代所有500?如果我正在编写这个函数,我将完全失去迭代:

function getNotifyPartyOrCustomer(orderID varchar2) return varchar2 is
NameResult varchar2(100);

CURSOR c_involved_party is
  select involved_party_contact_gid
    from order_release_inv_party
   where involved_party_qual_gid in ('NOTIFY PARTY', 'CUSTOMER')
     and order_release_gid = orderID
   order by involved_party_qual_gid desc;

v_contact_gid order_release_inv_party.involved_party_contact_gid%type;
begin

open c_involved_party;
fetch c_involved_party into v_contact_gid;
close c_involved_party;

return v_contact_gid;

end getNotifyPartyOrCustomer;

答案 1 :(得分:0)

希望这有效 - 抱歉,如果有任何语法或编译问题,但你明白了 -

CREATE OR REPLACE FUNCTION getnotifypartyorcustomer (orderid VARCHAR2)
   RETURN VARCHAR2
IS
   nameresult   VARCHAR2 (100);

   CURSOR c_involved_party
   IS
      SELECT CASE
                WHEN involved_party_contact_gid =
                                         'CUSTOMER'
                   THEN involved_party_qual_gid
                ELSE NULL
             END involved_party_qual_gid_a,
             CASE
                WHEN involved_party_contact_gid =
                                     'NOTIFY PARTY'
                   THEN involved_party_qual_gid
                ELSE NULL
             END involved_party_qual_gid_b
        FROM order_release_inv_party
       WHERE involved_party_qual_gid IN ('NOTIFY PARTY', 'CUSTOMER')
         AND order_release_gid = orderid;
BEGIN
   FOR i IN c_involved_party
   LOOP
      nameresult :=
         NVL (NVL (i.involved_party_qual_gid_a, i.involved_party_qual_gid_b),
              'NONE'
             );
   END LOOP;

   RETURN (nameresult);
EXCEPTION WHEN OTHERS 
    RETURN nameresult;
    -- or RAISE if You Want
END;

CREATE OR REPLACE FUNCTION getnotifypartyorcustomer (orderid VARCHAR2)
RETURN VARCHAR2
IS
   nameresult   VARCHAR2 (100);
BEGIN
SELECT NVL (NVL (involved_party_qual_gid_a, involved_party_qual_gid_b),'NONE')
  INTO nameresult
  FROM (SELECT CASE
                  WHEN involved_party_contact_gid =
                                         'CUSTOMER'
                     THEN involved_party_qual_gid
                  ELSE NULL
               END involved_party_qual_gid_a,
               CASE
                  WHEN involved_party_contact_gid =
                                     'NOTIFY PARTY'
                     THEN involved_party_qual_gid
                  ELSE NULL
               END involved_party_qual_gid_b
          FROM order_release_inv_party
         WHERE involved_party_qual_gid IN ('NOTIFY PARTY', 'CUSTOMER')
           AND order_release_gid = orderid)
       );

   RETURN (nameresult);
EXCEPTION WHEN OTHERS 
    RETURN NULL ;
    -- RETURN 'NONE' ;
END;