找不到几个Select Into语句的Oracle No Data

时间:2015-05-20 21:16:19

标签: oracle exception plsql

我在PL / SQL过程中使用了几个连续的SELECT INTO语句。如果这些Select语句中的任何一个导致NO DATA FOUND,我想以一致的方式处理错误。有没有办法在几个Select语句的同一过程中使用一个EXCEPTION例程?我想知道哪个特定的选择失败,以便我能给出正确的信息。

Declare
  l_smtp_hostname varchar2(1024);
  l_smtp_port varchar2(1024);
  l_music_db_site varchar2(1024);
Begin
    Select lu_value into l_smtp_hostname from mail_lookup 
          Where lu_type = 'smtp_hostname';
    Select lu_value into l_smtp_port from mail_lookup 
          Where lu_type = 'smtp_port';
    Select lu_value into l_music_db_site from mail_lookup 
          Where lu_type = 'music_db_site';
End;

感谢您查看此内容。

2 个答案:

答案 0 :(得分:3)

实际上,可能不是。

您可以拥有一个异常处理程序,但后来您不知道哪个步骤失败了。您可能会从错误堆栈中获取错误的行号,然后从dba_source解析数据(假设您确实有一个存储过程而不是匿名PL / SQL块)来查找该语句。但那是一项艰苦的工作。

Declare
  l_smtp_hostname varchar2(1024);
  l_smtp_port varchar2(1024);
  l_music_db_site varchar2(1024);
Begin
    Select lu_value into l_smtp_hostname from mail_lookup 
          Where lu_type = 'smtp_hostname';
    Select lu_value into l_smtp_port from mail_lookup 
          Where lu_type = 'smtp_port';
    Select lu_value into l_music_db_site from mail_lookup 
          Where lu_type = 'music_db_site';
Exception
  When no_data_found
  Then
    <<do something>>
End;

您可以添加一个跟踪您在此过程中所处位置的变量。这可行,但可能导致一些丑陋的代码

Declare
  l_smtp_hostname varchar2(1024);
  l_smtp_port varchar2(1024);
  l_music_db_site varchar2(1024);

  l_tracker varchar2(30);
Begin
    l_tracker := 'smtp_hostname';
    Select lu_value into l_smtp_hostname from mail_lookup 
          Where lu_type = l_tracker;

    l_tracker := 'smtp_port';
    Select lu_value into l_smtp_port from mail_lookup 
          Where lu_type = l_tracker;

    l_tracker := 'music_db_site';
    Select lu_value into l_music_db_site from mail_lookup 
          Where lu_type = l_tracker;
Exception
  When no_data_found
  Then
    dbms_output.put_line( 'Error at ' || l_tracker );
    <<do something>>
End;

大多数情况下,您希望单独处理每个例外。通常通过调用记录错误的过程。

Declare
  l_smtp_hostname varchar2(1024);
  l_smtp_port varchar2(1024);
  l_music_db_site varchar2(1024);
Begin
  begin
    Select lu_value into l_smtp_hostname from mail_lookup 
          Where lu_type = 'smtp_hostname';
  exception
    when no_data_found then
      log_error( 'smtp_hostname', <<other parameters>> );
  end;

  begin
    Select lu_value into l_smtp_port from mail_lookup 
          Where lu_type = 'smtp_port';
  exception
    when no_data_found then
      log_error( 'smtp_port', <<other parameters>> );
  end;

  begin
    Select lu_value into l_music_db_site from mail_lookup 
          Where lu_type = 'music_db_site';
  exception
    when no_data_found then
      log_error( 'music_db_site', <<other parameters>> );
  end;
End;

当然,您可以将该代码并将其分解为一个函数,该函数需要lu_type并返回lu_value而不是复制块中的代码。

Declare
  l_smtp_hostname varchar2(1024);
  l_smtp_port varchar2(1024);
  l_music_db_site varchar2(1024);

  function get_lu_value( p_lu_type in mail_lookup.lu_type%type )
    return mail_lookup.lu_value%type
  is
    l_val mail_lookup.lu_value%type;
  begin
    select lu_value
      into l_val
      from mail_lookup
     where lu_type = p_lu_type;

    return l_val;
  exception
    when no_data_found
    then
      <<do something>>
  end;
Begin
  l_smtp_hostname := get_lu_value( 'smtp_hostname' ); 
  l_smtp_port := get_lu_value( 'smtp_port' ); 
  l_music_db_site := get_lu_value( 'music_db_site' ); 
End;

答案 1 :(得分:2)

您可以将每个选择包装在其自己的块中并调用公共异常处理程序,或者执行类似这样的操作,在您通过代码时设置位置变量,如果发生异常,请记录该值的位置,所以你知道它失败的地方:

Declare
  l_smtp_hostname varchar2(1024);
  l_smtp_port     varchar2(1024);
  l_music_db_site varchar2(1024);
  v_location      varchar2(50);
  err_nbr         NUMBER;         -- Holds a SQL error number if an exception occurs.
  err_msg         VARCHAR2(1000); -- Holds a SQL error message if an exception occurs.
  err_string      VARCHAR2(2000);
Begin
    v_location := 'location_1';
    Select lu_value into l_smtp_hostname from mail_lookup 
          Where lu_type = 'smtp_hostname';
    v_location := 'location_2';
    Select lu_value into l_smtp_port from mail_lookup 
          Where lu_type = 'smtp_port';
    v_location := 'location_3';
    Select lu_value into l_music_db_site from mail_lookup 
          Where lu_type = 'music_db_site';
Exception
  When NO_DATA_FOUND then
    err_nbr    := SQLCODE;
    err_msg    := SUBSTR(SQLERRM, 1, 1000);
    err_string := 'ERROR: ' || err_nbr || ' occurred: ' || err_msg;

    UTL_MAIL.send(sender     => 'program_name@your_company.com', 
                  recipients => 'support_team@your_company.com', 
                  subject    => 'ERROR in <program_name>', 
                  message    => 'Select failed at: ' || v_location || CHR(10)||CHR(10)||err_string);                                  

  RAISE; -- re-raise the error so the program fails.
End;