输入创建和执行

时间:2017-12-08 10:34:21

标签: oracle oracle11g

我创建了一个类型,用于从员工表中打印员工的经验,为5名员工提供一个不正确的ID。我创建了一个异常来跳过它,但我没有得到它的结果。我做错了什么?请参考我的查询并告诉错误。

var output = temp1.reduce( (a,b) => a.concat(b) ,[] ) ;

提前致谢...

1 个答案:

答案 0 :(得分:2)

您在过程和匿名块中都有多个错误。在程序中:

  • 您尚未初始化OUT p_exp集合。由于它是一个OUT参数,您必须在程序中执行此操作。 (或者将其设为IN OUT)。
  • 您的异常处理程序终止循环,因此您在其中设置的v_exp从未使用过,p_exp集合不完整。 (使用when others也是不好的做法。)
  • 您不能为数字变量或集合分配像``NULL'`这样的字符串。为调用者分配一个表示错误的幻数,或将其保留为空。
CREATE OR REPLACE PROCEDURE exp_sp ( p_empid   IN  emp_id_typ
                                   , p_exp     OUT emp_exp_typ)
IS
  v_exp   NUMBER;
BEGIN
  -- have to initialise p_exp
  p_exp := emp_exp_typ();
  -- better to use either 1..count, or first..last; don't mix them
  --FOR i IN p_empid.FIRST..p_empid.COUNT
  FOR i IN p_empid.FIRST..p_empid.LAST
  LOOP
    p_exp.EXTEND;
    -- you want the exception handler to deal with this row then continue,
    -- so use a nested block
    BEGIN
      SELECT ROUND(MONTHS_BETWEEN(SYSDATE, hire_date)/12) INTO v_exp FROM employees
      WHERE employee_id = p_empid(i);
    EXCEPTION
      WHEN OTHERS THEN
        -- you can't assign a string to a number
        --v_exp := NVL(v_exp, 'NULL');
        -- just an example as not clear what you need
        v_exp := -1;
    END; -- nested block with exception handler
    p_exp(p_exp.LAST) := v_exp;
  END LOOP;
END exp_sp;
/

在您的匿名栏中:

  • v_exp的初始化是多余的,因为过程参数是OUT。不是错误,而是毫无意义。
  • 您正在调用循环内的过程,传递单个元素;它应该在循环外调用一次并传递整个集合。
  • 您对dbms_output.put_line的来电是错误的;只需要一个参数,所以你必须建立一个字符串,例如连接。
DECLARE
  v_empid emp_id_typ := emp_id_typ( );
  -- assignment is redundant
  -- v_exp   emp_exp_typ := emp_exp_typ( );
  v_exp   emp_exp_typ;
BEGIN
  v_empid := emp_id_typ(101, 102, 52, 100, 206);
  -- moved this call up, without indexing
  exp_sp(v_empid, v_exp);
  -- better to use either 1..count, or first..last; don't mix them
  -- FOR i IN v_empid.FIRST..v_empid.COUNT
  FOR i IN v_empid.FIRST..v_empid.LAST
  LOOP
    --exp_sp(v_empid(i), v_exp(i));
    -- fixed call to dbms_output
    dbms_output.put_line(v_empid(i) ||': '|| v_exp(i));
  END LOOP;
END;
/

得到:

101: 28
102: 25
52: -1
100: 30
206: 24


PL/SQL procedure successfully completed.
  

我不需要打印第三个变量,因为它不在表中。

您可以测试幻数的v_exp值(或者为null,这更安全,但需要稍微修改该过程),并且只打印您需要的结果:

...
  FOR i IN v_empid.FIRST..v_empid.LAST
  LOOP
    IF v_exp(i) != -1 THEN
      dbms_output.put_line(v_empid(i) ||': '|| v_exp(i));
    END IF;
  END LOOP;
...

得到:

101: 28
102: 25
100: 30
206: 24

PL/SQL procedure successfully completed.