对于plsql

时间:2016-11-02 12:53:43

标签: sql plsql

我有一个包裹:

create or replace package body package_name
as 
procedure 
update_dte
cursor cur_variable is 
select person_id, eff_start_date, eff_end_date from tab_abc;

begin

open cursor cur_variable;
loop
num_count := cur_variable%ROWCOUNT;

for i in 1..num_count
loop
fetch cursor cur_variable
into l_person_id, l_eff_start_date, l_eff_end_date;

update tab_abc
set l_eff_start_date='31-dec-4712'
where person_id=l_person_id;
end loop;
end loop;
close cur_variable;

end;
end;
/

我在游标循环中使用循环的查询进入无限循环。基本上我想通过光标直到它的行数,这样就不会错过任何迭代更新。

2 个答案:

答案 0 :(得分:3)

您的代码没有按预期工作,因为a)您缺少外部循环的exit子句,b)直到您至少获取了行,%ROWCOUNT将返回0(即使它有如果您希望它返回光标中的行数,那么您可能会误认为 - 我们只会知道光标返回的行数一次&#39 ;完成从光标中获取所有行),c)使用l_eff_start_date = '31-dec-4712'您试图将变量设置为更新语句的一部分 - 这没有意义! - 和d)你还没有声明l_person_id,l_eff_start_date,l_eff_end_date或num_count变量。

您有一些选择 - 首先,这是您的代码应该是什么样的 - 您根本不需要外部循环:

create or replace package body package_name
as 
  procedure update_dte
  is

    cursor cur_variable is 
    select person_id, eff_start_date, eff_end_date
    from   tab_abc;

  begin
    open cursor cur_variable;
    loop
      fetch cursor cur_variable
      into l_person_id, l_eff_start_date, l_eff_end_date;

      exit when cur_variable%notfound;

      update tab_abc
      set    start_date = to_date('31-12-4712', 'dd-mm-yyyy') -- assuming start_date is of DATE datatype;
      where  person_id=l_person_id;
    end loop;

    close cur_variable;

  end update_dte;
end package_name;
/

但是,有一种更简单的循环游标方式,您不必担心创建变量以将值返回,打开或关闭游标或获取记录 - 游标-for-loop将为您处理所有这些:

create or replace package body package_name
as 
  procedure update_dte
  is

    cursor cur_variable is 
    select person_id, eff_start_date, eff_end_date
    from   tab_abc;

  begin
    for rec in cur_variable;
    loop
      update tab_abc
      set    start_date = to_date('31-12-4712', 'dd-mm-yyyy') -- assuming start_date is of DATE datatype;
      where  person_id=l_person_id;
    end loop;
  end update_dte;
end package_name;
/

然而,更好,更高效的是使用单个更新语句一次性完成工作,而不是逐行。在您的情况下,您甚至不需要光标循环,因为您正在更新tab_abc中的所有行,因此您的更新变得简单:

create or replace package body package_name
as 
  procedure update_dte
  is
  begin
    update tab_abc
    set    start_date = to_date('31-12-4712', 'dd-mm-yyyy'); -- assuming start_date is of DATE datatype;
  end update_dte;
end package_name;
/

在所有三种情况下,我都假设您正在尝试更新start_date列(以及它的DATE数据类型)。如果情况并非如此,则需要更新您的问题,以包含有关您尝试执行此过程的更多详细信息。这是一个家庭作业问题吗?

答案 1 :(得分:0)

原因很明显:你没有退出条件。另外,我不太清楚为什么你需要两个循环。那么你只需要一个内循环。

添加退出条件(不要忘记确切的语法),例如:

EXIT WHEN cur_variable%NOT_FOUND ;

这应该在FETCH

之后

顺便说一句,您不需要检查记录数量。只需循环(永远)并在FETCH没有返回结果时退出。