Oracle 11g: In PL/SQL is there any way to get info about inserted and updated rows after MERGE DML statement?

StackOverflow https://stackoverflow.com/questions/19156418

I would like to know is there any way to receive information in PL/SQL how many rows have been updated and how many rows have been inserted while my PL/SQL script using MERGE DML statement.

Let's use Oracle example of merge described here: MERGE example

This functionality is used in my function but also I'd like to log information how many rows has beed updated and how many rows have been inserted.

有帮助吗?

解决方案

There is a not a built-in way to get separate insert and update counts, no. SQL%ROWCOUNT would tell you the number of rows merged, as you probably already know, but there is no equivalent to get separate values for the inserts and updates.

This article by Adrian Billington shows a way to get the information by including a function call in the merge, which might add a little overhead.

There's a similar, and perhaps simpler, trick from MichaelS on the Oracle forums, which I can't take any credit for at all either, of course. I'm tempted to reproduce it here but I'm not sure if that's allowed, but essentially it's using sys_context to maintain a count, in much the same way that Adrian's solution did with a package variable. I'd use that one, as it's cleaner and I think it's easier to follow and maintain.

Still perilously close to a link-only answer but I don't want to plagiarise others' work either...

其他提示

Workarounds pointed by @AlexPoole works, but for me it's strange why don't count updates, inserts and even possible deletes by more natural way with triggers.

Suppose we have simple test table:

create table test_table (id number, col number)

Define simple package for counters

create or replace package pkg_test_table_counter as

  procedure reset_counter;

  procedure count_insert;
  procedure count_update;
  procedure count_delete;

  function get_insert_count return number;
  function get_update_count return number;
  function get_delete_count return number;

end;

... and package body:

create or replace package body pkg_test_table_counter as

  vUpdateCount number := 0;
  vInsertCount number := 0;
  vDeleteCount number := 0;

  procedure reset_counter is
  begin
    vUpdateCount := 0;
    vInsertCount := 0;
    vDeleteCount := 0;
  end;

  procedure count_insert is
  begin
    vInsertCount := vInsertCount + 1;
  end;

  procedure count_update is
  begin
    vUpdateCount := vUpdateCount + 1;
  end;

  procedure count_delete is
  begin
    vDeleteCount := vDeleteCount + 1;
  end;

  function get_insert_count return number is
  begin
    return vInsertCount;
  end;

  function get_update_count return number is
  begin
    return vUpdateCount;
  end;

  function get_delete_count return number is
  begin
    return vDeleteCount;
  end;

end;

To count number of rows during execution of single DML statement we need to reset it in before statement trigger

create or replace trigger trg_test_table_counter_reset 
  before insert or update or delete on test_table
begin
  pkg_test_table_counter.reset_counter;
end;

... and increment appropriate counter in trigger for each row:

create or replace trigger trg_test_table_counter_count 
  before insert or update or delete on test_table
  for each row
begin
  if inserting then 
    pkg_test_table_counter.count_insert;
  end if;
  if updating then 
    pkg_test_table_counter.count_update;
  end if;
  if deleting then 
    pkg_test_table_counter.count_delete;
  end if;
end;

So, after executing MERGE statement without additional tricks inside DML query text it's always possible to get exact number of affected rows:

select 
  pkg_test_table_counter.get_insert_count    insert_count,
  (
    pkg_test_table_counter.get_update_count
    -
    pkg_test_table_counter.get_delete_count
  )                                          update_count,
  pkg_test_table_counter.get_delete_count    delete_count
from dual

Note that delete operations also counted as updates for MERGE , but to keep package useful for another operations there are two separate counters.

SQLFiddle test

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top