当值不存在时无法'SELECT INTO'

时间:2012-08-22 19:52:20

标签: oracle plsql package select-into

SELECT Value1 INTO lValue
FROM   Table1
WHERE  Field1 = lTempValue;

匹配为true时,此方法正常。但如果匹配不成立,我会收到错误。

ORA-01403: no data found

理想情况下,这对我来说很好,因为我要检查旁边的值是否高于0,如果是,请在插入查询中使用该值。我不想检查值,然后必须运行相同的查询来检索它本质上,如果可能的话,我想在一个查询中执行它,但我无法弄清楚如何完成。

如果有值,那么我希望该值进入lValue。如果没有值,那么我希望0进入lValue。有人有任何想法吗?我只是做了一个快速谷歌检查,但它干了。想看,我会在看的时候发布这个。谢谢你的帮助。

5 个答案:

答案 0 :(得分:14)

通常情况下,您只需捕获异常

BEGIN
  SELECT value1
    INTO lValue
    FROM table1
   WHERE field1 = lTempValue;
EXCEPTION
  WHEN no_data_found
  THEN
    lvalue := 0;
END;

您可以使用NVL和聚合函数(MINMAX)来编写更少的代码,但这往往不太明显(例如,请注意那些答案必须修改几次)。并且它要求跟随你的人暂停片刻以了解你在做什么(以及你是否正确地做到了)。一个简单的嵌套PL / SQL块很常见且非常容易理解。

然而,不仅如此,它不会隐藏由于重复行而导致的错误。如果恰好在table1 field1 lTempValue no_data_found中获得两行,则仅捕获too_many_rows异常会将意外的{{1}}异常传播到调用者。由于您不希望有多行,这正是您想要的行为。使用聚合函数隐藏了以下事实:基础数据存在问题,导致您返回可能不正确的结果,并且无法检测到存在问题。一旦某些东西导致重复的行出现,我总是会发现错误 - 允许我在问题失控之前解决问题 - 而不是多年后发现我们已经有数百万个重复的行,代码偶尔会返回错误的结果,并且在解决根本原因后我们会进行大量的数据清理工作。

答案 1 :(得分:3)

作为Justin Cave的建议的替代方法,您可以稍微重写查询,以便它总是返回一行 - 如下所示:

SELECT NVL(Value1, 0) INTO lValue
FROM   Table1
RIGHT
JOIN   dual
ON     Field1 = lTempValue

答案 2 :(得分:2)

似乎每个人都真的过于复杂,假设你的值不是像记录或clobs这样奇怪的类型:

SELECT NVL(MIN(Value1), 0) INTO lValue
FROM   Table1
WHERE  Field1 = lTempValue;

答案 3 :(得分:1)

我会把它作为游标 - 只是为了安全(因为,我不喜欢我的存储过程中像BEGIN ....END;这样的散乱PLSQL块的想法),类似

CREATE OR REPLACE .....
...

 CURSOR c_get_val IS
 SELECT Value1 
 FROM   Table1
 WHERE  Field1 = lTempValue;

 lValue    Table1.Value1%TYPE;
 lTempValue  Table1.Table1%TYPE;

然后,

BEGIN
...
....
 /* populate lTempValue */

 OPEN c_get_val;
 FETCH c_get_val INTO lValue;
 if c_get_val%NOTFOUND    --this is where you handle ORA-01403: no data found
 then
   lValue := 0;
   /*or call a function, do some other stuff*/
 end if;
 CLOSE c_get_val; 
...
...
EXCEPTION
  /*do some smart exception handling here*/
END;

有关cursorsmore以及部分more的一些信息。

答案 4 :(得分:-1)

BEGIN
  SELECT value1
    INTO lValue
    FROM table1
   WHERE field1 = lTempValue;
EXCEPTION
  WHEN no_data_found
  THEN
    lvalue := 0;
EXCEPTION
  WHEN too_many_rows
  THEN
    lvalue := 0;
END;