Oracle 11g:在PL / SQL中有没有办法在MERGE DML语句之后获取有关插入和更新行的信息?

时间:2013-10-03 10:08:31

标签: oracle plsql merge oracle11g dml

我想知道有没有办法在PL / SQL中接收已更新的行数以及使用MERGE DML语句在我的PL / SQL脚本中插入了多少行。

让我们使用这里描述的Oracle合并示例:MERGE example

此功能在我的函数中使用,但我也想记录信息已更新的行数和已插入的行数。

2 个答案:

答案 0 :(得分:5)

有一种内置的方法可以获得单独的插入和更新计数,没有。 SQL%ROWCOUNT会告诉你合并的行数,正如您可能已经知道的那样,但没有相应的内容可以为插入和更新获取单独的值。

This article by Adrian Billington显示了一种通过在合并中包含函数调用来获取信息的方法,这可能会增加一些开销。

MichaelS on the Oracle forums有一个类似的,也许更简单的伎俩,当然,我也不能相提并论。我很想在这里重现它,但我不确定是否允许这样做,但基本上它使用sys_context来维持计数,这与Adrian的解决方案对包变量的方式非常相似。我会使用那个,因为它更干净,我认为它更容易遵循和维护。

仍然危险地接近仅限链接的答案,但我不想剽窃别人的工作......

答案 1 :(得分:3)

@AlexPoole指出的变通方法有效,但对我而言,奇怪的是为什么不用触发器更自然地计算更新,插入甚至可能的删除。

假设我们有简单的测试表:

create table test_table (id number, col number)

定义计数器的简单包

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;

...和包体:

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;

要计算执行单个DML语句期间的行数,我们需要在语句触发器

之前重置它
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;

...并在每行的触发器中增加适当的计数器:

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;

因此,在执行MERGE语句后,在DML查询文本中没有额外的技巧时,总是可以获得确切数量的受影响的行:

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

请注意,删除操作也算作MERGE的更新,但为了保持包对其他操作有用,有两个单独的计数器。

<强> SQLFiddle test