存储过程中的光标完成并卡住(Oracle Linux VM 上的 Oracle 11g)

Posted

技术标签:

【中文标题】存储过程中的光标完成并卡住(Oracle Linux VM 上的 Oracle 11g)【英文标题】:Cursor in stored procedure finishes and get stuck (Oracle 11g on Oracle Linux VM) 【发布时间】:2015-05-06 20:35:13 【问题描述】:

我在 Oracle VM VirutalBox 中安装了 Oracle Linux 11g。 (分配 4GB RAM) 我有一个有几个表的用户。我在这个用户的模式中创建了一个使用游标的过程:

CREATE OR REPLACE PROCEDURE SHOW_STATS (p_emp_id IN number)
IS
     v_name     varchar2(50);
     CURSOR c_stat IS
       SELECT J.IS_DESCRIPTION as st_name, count(*) AS st_count 
       FROM inventory I , inventory_status J
       WHERE I.STATUS=J.IS_ID and I.EMPLOYEE_ID = p_emp_id
       GROUP BY J.IS_DESCRIPTION;
       c_stat_rec c_stat%rowtype;
BEGIN
       IF NOT c_stat%ISOPEN THEN 
          OPEN c_stat;
     END IF;
       SELECT first_name || ' ' || last_name
       INTO v_name
       FROM employees
       WHERE employee_id = p_emp_id;

       DBMS_OUTPUT.PUT_LINE ('Employee ' || v_name || ' Stats:');
       DBMS_OUTPUT.PUT_LINE ('-----------------------------------------');

       LOOP
           FETCH c_stat INTO c_stat_rec ;
           EXIT WHEN c_stat%NOTFOUND ;
           DBMS_OUTPUT.PUT_LINE (c_stat_rec.st_count || ' items in status ' || c_stat_rec.st_name);
       END LOOP;

END;

程序编译成功。 当我在笔记本电脑(Win8)上的 PL/SQL Developer 上测试该过程时 - 它在运行该过程后卡住了。即,当我通过一个简单的块进行测试时:

begin
  -- Call the procedure
  show_stats(10004);
end;

我已经在游标中尝试了 SELECT 语句 - 它运行并给出输出。

调试运行正常(由于某种原因,没有输出),但是当它退出该过程时,我得到了沙观察处理,PL/SQL 客户端卡住了,我不得不让它崩溃。

任何人都可以找到它发生的原因吗?

【问题讨论】:

您从哪个窗口运行调用,您是否看到任何 dbms_output?如果你看到那里有什么,如果你在循环之后添加另一条消息,你看到了吗?最后关闭光标有什么不同吗? (它不应该,但也许这会让调试器感到困惑?)你能从另一个客户端运行它吗,比如 VM 中的 SQL*Plus? 我运行 Windows 8.1 我没有看到任何 DBMS_OUTPUT 输出,这也让我感到困惑。关闭光标没有任何效果。当我从 VM 中的 sql*plus 运行该块时,我只收到一条消息,表明该块已成功编译 更新:当我从 SQL*Plus 运行块时,当我执行 'Exec show_stats();' 时,我确实看到了结果(我忘记设置服务器输出)。当我在 Windows 上运行 sql plus 时也是如此。所以 - 问题是,为什么 pl/sql 会卡住 我指的是哪个 PL/SQL Developer 窗口(SQL、命令、测试...我没有运行它,所以不记得其他的)而不是哪个版本的 Windows。你现在也看到那里的输出了吗?否则你为什么认为它在程序之后卡住了,而不是在循环中,说(也不应该卡在那里)。 它确实看起来像一个 PL/SQL 错误,但我对它还不够熟悉,无法识别它或提供太多帮助 - 主要是希望梳理出信息,以便其他人可以加入。只是删除所有 dbms_output 调用有什么不同吗?我已经更改了标签,希望能得到更合适的关注。祝你好运。 【参考方案1】:

您需要以/结束您的程序

PLSQL code
END;
/

【讨论】:

程序编译成功,并从其他客户端(包括同一客户端的更高版本)运行,所以不是问题。【参考方案2】:

你为什么不用这样的光标?

CREATE OR REPLACE PROCEDURE SHOW_STATS (p_emp_id IN number)
is
v_name varchar2(100);
begin
       SELECT first_name || ' ' || last_name
       INTO v_name
       FROM employees
       WHERE employee_id = p_emp_id;
for i in (
SELECT J.IS_DESCRIPTION as st_name, count(*) AS st_count 
       FROM inventory I , inventory_status J
       WHERE I.STATUS=J.IS_ID and I.EMPLOYEE_ID = p_emp_id
       GROUP BY J.IS_DESCRIPTION) loop
end loop;
exception
when others then
   dbms_output.put_line(sqlerrm);

end;

因此您不必担心关闭不在您的程序中的光标

【讨论】:

以上是关于存储过程中的光标完成并卡住(Oracle Linux VM 上的 Oracle 11g)的主要内容,如果未能解决你的问题,请参考以下文章

查看Oracle中存储过程长时间被卡住的原因

查看Oracle中存储过程长时间被卡住的原因

多次卡住调用oracle程序

在 Oracle -17110 中创建存储过程 - 警告:执行完成并出现警告

Oracle中的存储过程(Stored Procedure)

oracle中的存储过程,有啥作用,以及怎么在代码中使用?