【问题标题】:PL/SQL cannot loop select statement for missing valuesPL/SQL 不能为缺失值循环选择语句
【发布时间】:2017-03-03 11:39:22
【问题描述】:

HR Schema 中,我正在编写一个PL/SQL 块来获取并显示所有employee_id 从150 到200 的员工。

declare
     v_c    number(3) := 150 ;
     v_fn   varchar2(150);
begin
     for i in  v_c .. v_c + 50
     loop
     select first_name into v_fn from employees where employee_id = i;
     dbms_output.put_line(i || ' ' || v_fn);
     end loop;    
end;

但是,如果有从 150 到 200 的所有 employee_id 的数据,它就可以正常工作。

假设我缺少employee_id = 160 的数据,那么这就是输出。

Error report -
ORA-01403: no data found
ORA-06512: at line 7
01403. 00000 -  "no data found"
*Cause:    No data was found from the objects.
*Action:   There was no data from the objects which may be due to end of fetch.
150 Peter
151 David
152 Peter
153 Christopher
154 Nanette
155 Oliver
156 Janette
157 Patrick
158 Allan
159 Lindsey

如何跳过 160 的错误并显示其他员工直到 employee_id = 200

When the select query fails, The execution of the loop must continue.

注意:我无可救药地尝试在 EXCEPTION 中使用 GOTO。

【问题讨论】:

标签: oracle for-loop select plsql


【解决方案1】:

最简单的方法是使用 FOR 循环和 SELECT 语句,如下所示。希望这会有所帮助。

BEGIN
  FOR i IN
  (SELECT employee_id,first_name FROM employees WHERE employee_id BETWEEN 150 AND 200
  )
  LOOP
    dbms_output.put_line(i.employee_id||' '||i.first_name);
  END LOOP;
END;

【讨论】:

  • 这种方法更高效也更有弹性
【解决方案2】:

你可以这样试试

DECLARE
  v_c  NUMBER(3) := 150;
  v_fn VARCHAR2(150);
BEGIN
  FOR i IN v_c .. v_c + 50
  LOOP
    BEGIN
      SELECT first_name INTO v_fn FROM employees WHERE employee_id = i;
      dbms_output.put_line(i || ' ' || v_fn);
    EXCEPTION
    WHEN no_data_found THEN
      dbms_output.put_line('Employee not found, ID: ' || i);
      CONTINUE;
    END;
  END LOOP;
END;

【讨论】:

  • 谢谢。这行得通。但请记住性能,最好使用@VáclavKužel 指示的游标
【解决方案3】:

使用Cursors实现

DECLARE
  c_id         employees.employee_id%type;
  c_first_name employees.first_name%type;
  v_end        NUMBER(3);
  CURSOR c_max_id
  IS
    SELECT MAX(employee_id) 
    FROM employees;
  CURSOR c_employees ( v_start NUMBER,v_end NUMBER )
  IS
    SELECT employee_id,first_name
    FROM employees
    WHERE employee_id BETWEEN v_start AND v_end;
BEGIN
  OPEN c_max_id;
  LOOP
    FETCH c_max_id INTO v_end;
    EXIT
  WHEN c_max_id%NOTFOUND;
    OPEN c_employees(150, v_end);
    LOOP
      FETCH c_employees INTO c_id, c_first_name;
      EXIT
    WHEN c_employees%notfound;
      dbms_output.put_line(c_id || ' ' || c_first_name);
    END LOOP;
    CLOSE c_employees;
  END LOOP;
  CLOSE c_max_id;
END;

【讨论】:

  • ..max(employee_id) 在代码中不使用任何地方时有​​什么用??
  • 你做错了。检查如何将参数传递给游标。您的代码将失败
  • @XING 我已经更新了代码。然而,前面的代码也给了我输出。
猜你喜欢
  • 1970-01-01
  • 2020-09-09
  • 2014-08-05
  • 2019-04-06
  • 2012-02-26
  • 2014-10-18
  • 1970-01-01
  • 2018-06-27
  • 1970-01-01
相关资源
最近更新 更多