Oracle 游标没有从 SELECT 语句中填充?

Posted

技术标签:

【中文标题】Oracle 游标没有从 SELECT 语句中填充?【英文标题】:Oracle Cursor not being populated from SELECT statement? 【发布时间】:2013-03-14 10:41:36 【问题描述】:

我一直在编写一个存储过程来从表中选择一堆 ID,将结果集保存到游标中,然后遍历游标,根据焦点中的任何 ID 更新表中的行光标。计划添加更多条件语句,但到目前为止..

CREATE OR REPLACE PROCEDURE CHANGE_PESONAL_DETAILS
AS

CURSOR
person_cur
IS

select b.id
    from blah1 b
        inner join blah2 b2 on b.id = b2.fkid;
person_rec person_cur%ROWTYPE;

BEGIN
FOR person_rec in person_cur

LOOP

dbms_output.put_line
(
person_rec.id
);

UPDATE blah1 set Details = DetailsLineOne || ' ' || DetailsLineTwo WHERE id = person_rec.id;

END LOOP;
COMMIT;

END;

我在这里编译的很好,但执行时,更新永远不会发生。我已在输出行中添加以查看光标中的内容,但没有打印任何内容。

用于填充光标的我的 Select 语句本身运行良好,返回了我期望它返回的所有数据,但在上面执行时,什么也没有。好像 Begin 之后的所有内容都没有执行,虽然我不明白为什么如前所述,我的 Select 会自行返回结果。

也许在填充光标的上下文中某些行为有所不同?任何建议都会很棒..

【问题讨论】:

如果您以独立方式运行 cursor select then ,它是否返回任何数据(在您运行该过程的同一会话中)?当您运行该程序时,您是否有set serveroutput on(或者如果您使用的是 gui,则为等价物)? 你不需要光标。它只会让你的 UPDATE 效率低很多。 @DazzaL - 是的,当单独运行时,光标选择会返回我期望的数据,即使在添加了 set serveroutput on 之后,仍然没有打印输出。 【参考方案1】:

请检查没有光标和循环的过程。

CREATE OR REPLACE PROCEDURE CHANGE_PESONAL_DETAILS
AS
BEGIN
UPDATE blah1 set Details = DetailsLineOne || ' ' || DetailsLineTwo WHERE id IN (select b.id
    from blah1 b inner join blah2 b2 on b.id = b2.fkid);
END;

使用循环检查

CREATE OR REPLACE PROCEDURE CHANGE_PESONAL_DETAILS
AS
CURSOR person_cur IS
  select b.id
    from blah1 b
        inner join blah2 b2 on b.id = b2.fkid;

  person_rec person_cur%ROWTYPE;
BEGIN
    OPEN person_cur;
    LOOP
      FETCH person_cur INTO person_rec;
      EXIT WHEN person_cur%NOTFOUND;

      UPDATE blah1 set Details = DetailsLineOne || ' ' || DetailsLineTwo WHERE id = person_rec.id;
    END LOOP;
    CLOSE person_cur;
END;

【讨论】:

这样做很好。虽然我想在以后添加一些条件语句,所以将它保留为 proc 是我唯一的选择。【参考方案2】:

我们不能声明游标的rowtype 如果我们在for loop 中使用游标,for loop 中使用的变量将用于访问游标中的列。

所以删除rowtype 声明并尝试like 并在执行过程之前包含SET SERVEROUT ON 命令以查看结果(可打印语句)

CREATE OR REPLACE PROCEDURE CHANGE_PESONAL_DETAILS
AS

CURSOR person_cur IS
     select b.id from blah1 b inner join blah2 b2 on b.id = b2.fkid;
BEGIN
     FOR person_rec in person_cur LOOP
          dbms_output.put_line(person_rec.id);
          UPDATE blah1 set Details = DetailsLineOne || ' ' || DetailsLineTwo WHERE id = person_rec.id;
     END LOOP;
     COMMIT;
END;

【讨论】:

即使删除了行类型,我仍然没有运气。将输出替换为基本的“Hello World!”字符串,甚至没有输出。就好像在填充光标的选择语句之后甚至没有执行任何操作! 我认为你的 select 语句没有给出任何记录只需尝试只执行 select 语句,即 select b.id from blah1 b inner join blah2 b2 on b.id = b2.fkid; 并告诉我们结果。 select 语句返回我单独运行时期望的所有记录。 好的!尝试删除光标并在 for 循环中包含相同的选择语句,即 CREATE OR REPLACE PROCEDURE CHANGE_PESONAL_DETAILS AS begin For i in (select b.id as id from blah1 b inner join blah2 b2 on b.id = b2.fkid) loop dbms_output.put_line(person_rec.id); UPDATE blah1 set Details = DetailsLineOne || ' ' || DetailsLineTwo WHERE id = i.id; end loop; end;

以上是关于Oracle 游标没有从 SELECT 语句中填充?的主要内容,如果未能解决你的问题,请参考以下文章

oracle基础之游标的理解与使用

Oracle学习笔记—— 游标

oracle的游标cursor

Oracle游标 CURSOR实例详解

『ORACLE』 PLSQL游标的使用(11g)

oracle 游标操作 怎么判断SQL语句是不是查出数据