【问题标题】:stored procedure strange behaviour存储过程奇怪的行为
【发布时间】:2020-05-17 06:37:15
【问题描述】:

我有一个类似的查询

(SELECT ...
FROM T2
WHERE x=1)

select 返回一个插入到 T1 中的元组列表。 这么久,真好。

因为“1”可能会更改带有参数的存储过程。

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

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

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

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

上面的代码可能无法编译,只是为了演示。

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

【问题讨论】:

  • 这不是一个最小的可重现示例。请参阅:stackoverflow.com/help/minimal-reproducible-example。我们无法猜测您的实际代码是什么。不,不要发布您当前的全部代码。创建一些一次性表(在此处包括创建表语句),在这些表上创建触发器(在此处包括触发器代码),创建显示您的问题的小过程(在此处包括过程代码)。然后编写一个调用您的过程的脚本(将其包含在您的问题中)并解释您期望的结果。
  • 另外,你的措辞应该准确。你写的大部分句子都是无意义的。 Select 语句不返回“元组列表”。 '1' 可能会改变存储过程——什么?不,运行选择不会插入任何内容。没有查询插入语句这样的事情。

标签: oracle stored-procedures plsql oracle12c


【解决方案1】:

阅读您所描述的内容,听起来好像您滥用了过程的参数。这是一个说明我的意思的例子。

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

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 表中找到的所有行,如不涉及其他条件。

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

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>

好多了,不是吗?


如果这就是你所做的,现在你知道如何解决它了。如果没有,请像我一样发布一个示例,以便我们了解您的操作以及 Oracle 的响应方式。


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

【讨论】:

    猜你喜欢
    • 2015-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-13
    • 2022-11-18
    • 2017-06-21
    • 1970-01-01
    • 2021-06-10
    相关资源
    最近更新 更多