oracle存储过程无法正常工作

use*_*844 0 oracle stored-procedures

以下程序符合罚款,

 CREATE PROCEDURE PROCEDURE1
          (v_MGR int,
          v_empid IN OUT int)
    AS
    BEGIN
    v_empid :=0;
    IF (v_mgr IS NOT NULL AND v_mgr <> '') then
    EXECUTE IMMEDIATE 'SELECT EMPNO
          FROM EMP
       WHERE MGR = Rtrim(v_MGR)' into v_empid;
    END IF;
    END PROCEDURE1;
Run Code Online (Sandbox Code Playgroud)

但是当我跑

DECLARE
  V_MGR NUMBER;
  V_EMPID NUMBER;
BEGIN
  V_MGR := 7902;
  V_EMPID := NULL;

  PROCEDURE1(
    V_MGR => V_MGR,
    V_EMPID => V_EMPID
  );
  DBMS_OUTPUT.PUT_LINE('V_EMPID = ' || V_EMPID);
END;
Run Code Online (Sandbox Code Playgroud)

输出应为v_empid = 2356

但它始终显示v_empid = 0请帮助获得正确的答案

Nic*_*nov 5

  1. 为什么out参数为0?看一下if程序中的条件

    IF (v_mgr IS NOT NULL AND v_mgr <> '')
    
    Run Code Online (Sandbox Code Playgroud)

    特别是在第二部分AND v_mgr <> ''.Oracle将空字符串''视为null和任何比较null导致未知结果,因此上述IF条件总是计算为false,因此execute immediate语句永远不会执行,因此v_empid 永远不会覆盖该值.

  2. 在这种特殊情况下,绝对不需要使用动态SQL(本机动态sql execute immediate),因为没有动态构造的查询 - 表和列在编译时是已知的.你只需使用静态sql代替:

  3. 如果您的查询返回多行,您将遇到too_many_rows异常.您应该保证您的查询只返回一行,方法是rownum=1where查询的子句中包含(如果有更改返回多行)或者使用集合作为out参数,则返回结果集:

    create or replace type T_EmpNums is table of number;
    /
    
    create or replace procedure procedure1(
        v_mgr  int,
        v_emps out T_empnums
    )
    as
    begin
      if v_mgr is not null  
      then
         select empno
           bulk collect into v_emps
           from emp
          where mgr = v_mgr;
      end if;
    end;
    /
    
    declare
      v_mgr number;
      v_empids T_EmpNums;
    begin
      v_mgr := 7902;
      procedure1(v_mgr, v_empids);
      if v_empids is not empty
      then 
        for empno in v_empids.first .. v_empids.last
        loop
          dbms_output.put_line('v_empid = ' || to_char(v_empids(empno)));
        end loop;
      end if;
    end;
    
    Run Code Online (Sandbox Code Playgroud)