【问题标题】:Checking execution of procedure (PL/SQL, Oracle)检查过程的执行(PL/SQL、Oracle)
【发布时间】:2018-07-01 01:32:27
【问题描述】:

我有以下 PL/SQL 块:

Begin
   insert1();
   insert2();
   insert3();

   procedureTest();    
End

每个 insertTest 都在插入一些表。

现在,如果此过程之一不会插入任何内容,我的 procedureTest 不应执行。

怎么做?

【问题讨论】:

  • 你不需要了解交易和commit
  • 处理每个插入的异常。 stackoverflow.com/questions/12527507/…
  • insert1/2/3 程序没有插入任何东西时,这是这些程序中的错误情况吗?如果没有,他们可以通过out 参数返回行数吗?
  • 在这种情况下,您需要进行一些测试来检查是否应该执行 procedureTest。要么计算表中的行数,要么让insert1/2/3 过程传回您可以检查的内容,然后决定是否继续。
  • 我可以使用“SQL%ROWCOUNT”吗?

标签: sql oracle plsql procedure oracle12c


【解决方案1】:

您有两种可能检查三个过程是否插入行:

1) 启动查询或调用函数以选择每次调用后预期插入的行数;

2) 存储命令sql%rowcount 的结果:该命令返回受前面insert/update/delete 指令影响的行数。

注意,对于第二个选项,如果 insert1/2/3 仅使用一个插入指令插入行并且该单个插入是过程的最后一条语句,那么您可以在之后调用 sql%rowcount通过以下方式调用insert1/2/3

declare
   ret NUMBER := 0;
Begin
   insert1();
   ret := sql%rowcount; -- counts rows inserted in insert1

   insert2();
   ret := ret + sql%rowcount; -- counts rows inserted in insert1 + insert2

   insert3();
   ret := ret + sql%rowcount; -- counts rows inserted in insert1 + insert2 + insert3

   if ret > 0 then
      procedureTest();
   end if;
End

相反,如果三个过程各自使用多个插入语句或在插入后执行选择或任何其他指令,则必须在每次插入后立即检查sql%rowcount inside insert1/2/3语句并将这些结果的总和作为输出参数(如果 insert1/2/3 是过程)或返回值(如果 insert1/2/3 是函数)返回。

希望对你有帮助。

【讨论】:

  • 我认为运算符 += 在 Oracle PL/SQL 中不可用
  • @WernfriedDomscheit:你说得对……修改后的答案
  • 这依赖于将insert select 语句作为最后一个操作的insert1/2/3 过程。如果有人向他们添加日志记录或其他内容,那么逻辑就被打破了。
  • @WilliamRobertson:我已经在我的回答中指定了它...... :-)
【解决方案2】:

从这里

如果此过程之一不会插入任何内容

我了解到您想停止执行其余代码。因此,为此,建议是:在那些函数 insert1/2/3 中,返回受影响的行数:

sql%rowcount

请注意,此函数计算受影响的行数,可以说,它只计算插入、更新和删除语句(不是选择),对于选择,你需要一个游标,更多信息你可以在这里找到:https://asktom.oracle.com/pls/apex/asktom.search?tag=rows-affected

然后,由于这些函数返回一个值,如果插入任何内容将返回一个大于 0 的数字,那么您可以将 then 存储在一个变量中并检查它们的值,如果其中任何一个是 == 0,则返回,否则,执行procedureTest()。要中断执行,可以使用return;

【讨论】:

    【解决方案3】:

    一种方法是让您的insert1/2/3 过程返回作为OUT 参数插入的行数,然后您可以在调用过程中捕获和检查这些行数。

    declare
        l_rowcount1 integer := 0;
        l_rowcount2 integer := 0;
        l_rowcount3 integer := 0;
    
        l_rowcount_total integer := 0;
    
        procedure insert1
            ( p_rowcount out integer )
        is
        begin
            insert into sometable(a, b, c)
            select x, y, z from somewhere
            where  whatever = somethingelse;
    
            p_rowcount := sql%rowcount;
        end insert1;
    
    begin
        insert1(l_rowcount1);
        insert1(l_rowcount2);
        insert1(l_rowcount3);
    
        l_rowcount_total := l_rowcount1 + l_rowcount2 + l_rowcount3;
    
        if l_rowcount_total > 0 then
            do_something();
        end if;
    end;
    

    【讨论】:

      【解决方案4】:
      create or replace procedure insert1 is
        o_error varchar2(150);
      begin
        -- your statement 1
       exception when others then rollback; o_error := ' an error occured! '; raise_application_error(-20101,o_error);
      end;
      

      创建过程insert1 - 2 - 3 如前所述,在每个连续的插入过程中将错误代码迭代一个为-20002-20003,以及语句23

      然后像以前一样使用返回的错误参数调用:

      Begin
         insert1;
         insert2;
         insert3;
      
         procedureTest();    
      End
      

      如果出现任何错误,您会将其视为警报,并且您的程序单元将停止运行。

      【讨论】:

      • 明白你的意思,我可以这样做,但如果可能的话“抓住”插入?就像我想知道插入了多少行以及使用“IF”
      • @4est 正如其他朋友所说,您可以按 sql%rowcount 计数,但您的问题文本没有要求?(请使用此额外信息编辑您的问题)
      猜你喜欢
      • 1970-01-01
      • 2017-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多