在 Oracle Procedure 中使用 IN 参数似乎很好地对该参数起到保护作用, 其实不然! 请看如下 Code
-- Spec Part
PACKAGE TEST
IS
g1 NUMBER;
PROCEDURE proc1;
PROCEDURE proc2 (p1 IN NUMBER);
END;
-- Body Part
PACKAGE BODY TEST
IS
PROCEDURE proc1
IS
BEGIN
g1 := 1;
proc2 (g1);
DBMS_OUTPUT.put_line ('g1=' || g1);
END;
PROCEDURE proc2 (p1 IN NUMBER)
IS
c1 CONSTANT NUMBER := p1;
BEGIN
--p1 := p1 + 1; 这句是编译不通过的, 似乎已对 IN 参数保护了.
DBMS_OUTPUT.put_line ('p1=' || p1);
DBMS_OUTPUT.put_line ('c1=' || c1);
g1 := g1 + 1; -- 这句间接地改变了 IN 参数值!
DBMS_OUTPUT.put_line ('after p1=' || p1); -- 已经被改了!
DBMS_OUTPUT.put_line ('after c1=' || c1);
END;
END;
运行 proc1 后输出:
p1=1
c1=1
after p1=2
after c1=1
g1=2
总结:
1) 若要确保过程内任意地方都能访问到 IN 参数的初始值, 需要使用附加常量
2) 尽可能少用全局变量 (风险很大)
3) 其它非 Oracle 数据库也可能出现该情况.