存储过程奇怪的行为

stored procedure strange behaviour

我有一个类似

的查询
(SELECT ...
FROM T2
WHERE x=1)

select returns 插入T1的元组列表。 久违了,真好

因为“1”可能会更改带有参数的存储过程,所以这里可以完成工作。

BEGIN
    INSERT INTO T1
    (SELECT ...
    FROM T2
    WHERE x=value)
END;

该过程由 T3 上的触发器 AFTER INSERT 调用。

运行 Oracle 12c 上的 select 插入,例如两行进入 T1。 运行 不同的值而不是“1”也可以正常工作。

调用过程时,尽管使用不同的参数调用,但始终插入具有相同值的相同数量的行。看起来它是使用相同的参数执行的,但事实并非如此。 该过程的执行时间是直接查询插入语句的大约 18 倍。

以上代码可能无法编译,仅供演示。

知道为什么过程执行需要这么长时间以及为什么它显然在做某事。还有吗?

看了你的描述,好像你误用了程序的参数。这是一个说明我的意思的例子。

让我们创建一个 table(就像您拥有的 T1)和一个接受参数并执行插入到 table 的过程。

SQL> create table test (deptno number, ename varchar2(10));

Table created.

SQL>
SQL> create or replace procedure p_test (deptno in number)
  2  is
  3  begin
  4    insert into test (deptno, ename)
  5    select deptno, ename
  6    from emp
  7    where deptno = deptno;
  8  end;
  9  /

Procedure created.

我想插入在部门 10 工作的员工:

SQL> select deptno, ename
  2  from emp
  3  where deptno = 10;

    DEPTNO ENAME
---------- ----------
        10 CLARK
        10 KING
        10 MILLER

很好;我希望插入 3 行。让我们调用程序,然后:

SQL> exec p_test (10);

PL/SQL procedure successfully completed.

结果:

SQL> select * From test;

    DEPTNO ENAME
---------- ----------
        20 SMITH
        30 ALLEN
        30 WARD
        20 JONES
        30 MARTIN
        30 BLAKE
        10 CLARK
        20 SCOTT
        10 KING
        30 TURNER
        20 ADAMS
        30 JAMES
        20 FORD
        10 MILLER

14 rows selected.

SQL>

糟糕!不完全是我想要的。

罪魁祸首是:

7    where deptno = deptno;

因为我将参数命名为与列名完全一样,所以 Oracle 知道 这个条件总是成立的(就好像 where 1 = 1)并插入它在中找到的所有行EMP table,因为不涉及其他条件。

怎么办?重命名参数并重复测试:

SQL> create or replace procedure p_test (p_deptno in number)     --> here
  2  is
  3  begin
  4    insert into test (deptno, ename)
  5    select deptno, ename
  6    from emp
  7    where deptno = p_deptno;                                  --> here
  8  end;
  9  /

Procedure created.

SQL> truncate table test;

Table truncated.

SQL> exec p_test (10);

PL/SQL procedure successfully completed.

SQL> select * From test;

    DEPTNO ENAME
---------- ----------
        10 CLARK
        10 KING
        10 MILLER

SQL>

好多了,不是吗?


如果那是您所做的,那么现在您知道如何解决它了。如果没有,post 像我一样举个例子,这样我们就可以看到你做了什么以及 Oracle 是如何回应的。


截至程序讨论时间……好吧,谁知道呢?信息太少无法计算。跟踪会话并使用 TKPROF,您将确切地知道发生了什么。