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请帮助获得正确的答案
为什么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
永远不会覆盖该值.
在这种特殊情况下,绝对不需要使用动态SQL(本机动态sql execute immediate),因为没有动态构造的查询 - 表和列在编译时是已知的.你只需使用静态sql代替:
如果您的查询返回多行,您将遇到too_many_rows异常.您应该保证您的查询只返回一行,方法是rownum=1在where查询的子句中包含(如果有更改返回多行)或者使用集合作为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)| 归档时间: |
|
| 查看次数: |
1290 次 |
| 最近记录: |