【问题标题】:Number of rows affected by an UPDATE in PL/SQLPL/SQL 中受 UPDATE 影响的行数
【发布时间】:2010-10-26 02:35:21
【问题描述】:

我有一个 PL/SQL 函数(在 Oracle 10g 上运行),我在其中更新了一些行。有没有办法找出 UPDATE 影响了多少行?手动执行查询时,它告诉我有多少行受到影响,我想在 PL/SQL 中获取该数字。

【问题讨论】:

    标签: oracle plsql sql-update


    【解决方案1】:

    您使用sql%rowcount 变量。

    您需要在需要查找受影响的行数的语句之后直接调用它。

    例如:

    set serveroutput ON; 
    DECLARE 
        i NUMBER; 
    BEGIN 
        UPDATE employees 
        SET    status = 'fired' 
        WHERE  name LIKE '%Bloggs'; 
        i := SQL%rowcount; 
        --note that assignment has to precede COMMIT
        COMMIT; 
        dbms_output.Put_line(i); 
    END; 
    

    【讨论】:

    • 并且赋值必须在任何 COMMIT 之前
    • @Clive 我有一个带有INSERT INTO..COMMIT 的过程,并且在插入后的相同过程中,我有UPDATE SET WHERE EXISTS..COMMIT,但我的i := SQL%rowcount; 正在返回所有行而不是仅更新的行。可能是什么?
    【解决方案2】:

    对于那些想要从简单命令获得结果的人,解决方案可能是:

    begin
      DBMS_OUTPUT.PUT_LINE(TO_Char(SQL%ROWCOUNT)||' rows affected.');
    end;
    

    基本问题是 SQL%ROWCOUNT 是一个 PL/SQL 变量(或函数),不能从 SQL 命令直接访问。通过使用 noname PL/SQL 块,可以实现这一点。

    ...如果有人有在 SELECT 命令中使用它的解决方案,我会很感兴趣。

    【讨论】:

      【解决方案3】:

      或者,SQL%ROWCOUNT 您可以在过程中使用它而无需声明变量

      【讨论】:

      • SQL%ROWCOUNT 是一个函数,你不能只是“使用它”——你需要用它一些事情——无论是存储在变量中,还是将其发送为输入到另一个过程,或将其添加到其他东西。
      • 我认为 Ali H 的观点是,在您有另一个会影响行数的 SQL 语句之前,没有必要将其分配给变量。话虽如此,我同意应该将它分配给一个变量,以避免以后有人在调用它之前添加另一个 SQL 语句时导致错误。而且,来自 Ali H 的这个答案应该是对 Clive 答案的评论,而不是作为单独的答案发布
      【解决方案4】:

      SQL%ROWCOUNT 也可以在不分配的情况下使用(至少从 Oracle 11g 开始)。

      只要在当前块内没有执行任何操作(更新、删除或插入),SQL%ROWCOUNT 就会设置为 null。然后它停留在受上一次 DML 操作影响的行数:

      假设我们有表 CLIENT

      create table client (
        val_cli integer
       ,status varchar2(10)
      )
      /
      

      我们会这样测试它:

      begin
        dbms_output.put_line('Value when entering the block:'||sql%rowcount);
      
        insert into client 
                  select 1, 'void' from dual
        union all select 4, 'void' from dual
        union all select 1, 'void' from dual
        union all select 6, 'void' from dual
        union all select 10, 'void' from dual;  
        dbms_output.put_line('Number of lines affected by previous DML operation:'||sql%rowcount);
      
        for val in 1..10
          loop
            update client set status = 'updated' where val_cli = val;
            if sql%rowcount = 0 then
              dbms_output.put_line('no client with '||val||' val_cli.');
            elsif sql%rowcount = 1 then
              dbms_output.put_line(sql%rowcount||' client updated for '||val);
            else -- >1
              dbms_output.put_line(sql%rowcount||' clients updated for '||val);
            end if;
        end loop;  
      end;
      

      导致:

      Value when entering the block:
      Number of lines affected by previous DML operation:5
      2 clients updated for 1
      no client with 2 val_cli.
      no client with 3 val_cli.
      1 client updated for 4
      no client with 5 val_cli.
      1 client updated for 6
      no client with 7 val_cli.
      no client with 8 val_cli.
      no client with 9 val_cli.
      1 client updated for 10
      

      【讨论】:

        【解决方案5】:

        请试试这个..


        create table client (
          val_cli integer
         ,status varchar2(10)
        );
        
        ---------------------
        begin
        insert into client
        select 1, 'void' from dual
        union all
        select 4, 'void' from dual
        union all
        select 1, 'void' from dual
        union all
        select 6, 'void' from dual
        union all
        select 10, 'void' from dual;
        end;
        
        ---------------------
        select * from client;
        
        ---------------------
        declare
          counter integer := 0;
        begin
          for val in 1..10
            loop
              update client set status = 'updated' where val_cli = val;
              if sql%rowcount = 0 then
                dbms_output.put_line('no client with '||val||' val_cli.');
              else
                dbms_output.put_line(sql%rowcount||' client updated for '||val);
                counter := counter + sql%rowcount;
              end if;
          end loop;
           dbms_output.put_line('Number of total lines affected update operation: '||counter);
        end;
        
        ---------------------
        select * from client;
        
        --------------------------------------------------------
        

        结果如下:


        为 1 个更新了 2 个客户端
        没有带有 2 val_cli 的客户端。
        没有带有 3 val_cli 的客户端。
        1 个客户端更新为 4
        没有 5 val_cli 的客户端。
        1 个客户端更新为 6
        没有带有 7 val_cli 的客户端。
        没有 8 val_cli 的客户端。
        没有 9 val_cli 的客户端。
        1 个客户更新了 10
        影响更新操作的总行数:5


        【讨论】:

        • 将 cmets 添加到您的解决方案中,请具体说明。
        【解决方案6】:

        使用 Count(*) 分析函数 OVER PARTITION BY NULL 这将计算总行数

        【讨论】:

        • 在运行更新语句后,如果您检查实际更新内容的计数 - 这并没有提供任何通用解决方案。例如,如果我的表 T 有一个列 c1,其中包含“1”作为 all 的值,现在我将该列的所有行更新为“2”,那么 null 分区将如何帮助?
        猜你喜欢
        • 2011-10-28
        • 1970-01-01
        • 2013-01-08
        • 1970-01-01
        • 2016-11-01
        • 2013-01-21
        • 2016-08-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多