Oracle PL/SQL - Are NO_DATA_FOUND Exceptions bad for stored procedure performance?

后端 未结 12 849
Happy的楠姐
Happy的楠姐 2021-02-03 23:14

I\'m writing a stored procedure that needs to have a lot of conditioning in it. With the general knowledge from C#.NET coding that exceptions can hurt performance, I\'ve always

相关标签:
12条回答
  • 2021-02-04 00:06

    If it's important you really need to benchmark both options!

    Having said that, I have always used the exception method, the reasoning being it's better to only hit the database once.

    0 讨论(0)
  • 2021-02-04 00:06

    The count(*) will never raise exception because it always returns actual count or 0 - zero, no matter what. I'd use count.

    0 讨论(0)
  • 2021-02-04 00:08

    The first (excellent) answer stated -

    The method with count() is unsafe. If another session deletes the row that met the condition after the line with the count(*), and before the line with the select ... into, the code will throw an exception that will not get handled.

    Not so. Within a given logical Unit of Work Oracle is totally consistent. Even if someone commits the delete of the row between a count and a select Oracle will, for the active session, obtain the data from the logs. If it cannot, you will get a "snapshot too old" error.

    0 讨论(0)
  • 2021-02-04 00:12

    An alternative to @Steve's code.

    DECLARE
      CURSOR foo_cur IS 
        SELECT NEEDED_FIELD WHERE condition ;
    BEGIN
      FOR foo_rec IN foo_cur LOOP
         ...
      END LOOP;
    EXCEPTION
      WHEN OTHERS THEN
        RAISE;
    END ;
    

    The loop is not executed if there is no data. Cursor FOR loops are the way to go - they help avoid a lot of housekeeping. An even more compact solution:

    DECLARE
    BEGIN
      FOR foo_rec IN (SELECT NEEDED_FIELD WHERE condition) LOOP
         ...
      END LOOP;
    EXCEPTION
      WHEN OTHERS THEN
        RAISE;
    END ;
    

    Which works if you know the complete select statement at compile time.

    0 讨论(0)
  • 2021-02-04 00:12

    May be beating a dead horse here, but I bench-marked the cursor for loop, and that performed about as well as the no_data_found method:

    declare
      otherVar  number;
    begin
      for i in 1 .. 5000 loop
         begin
           for foo_rec in (select NEEDED_FIELD from t where cond = 0) loop
             otherVar := foo_rec.NEEDED_FIELD;
           end loop;
           otherVar := 0;
         end;
       end loop;
    end;
    

    PL/SQL procedure successfully completed.

    Elapsed: 00:00:02.18

    0 讨论(0)
  • 2021-02-04 00:13

    Since SELECT INTO assumes that a single row will be returned, you can use a statement of the form:

    SELECT MAX(column)
      INTO var
      FROM table
     WHERE conditions;
    
    IF var IS NOT NULL
    THEN ...
    

    The SELECT will give you the value if one is available, and a value of NULL instead of a NO_DATA_FOUND exception. The overhead introduced by MAX() will be minimal-to-zero since the result set contains a single row. It also has the advantage of being compact relative to a cursor-based solution, and not being vulnerable to concurrency issues like the two-step solution in the original post.

    0 讨论(0)
提交回复
热议问题