1

我想知道在我的 PL/SQL 脚本使用 MERGE DML 语句时,有什么方法可以在 PL/SQL 中接收信息,更新了多少行以及插入了多少行。

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

此功能在我的函数中使用,但我还想记录更新了多少行以及插入了多少行的信息。

4

2 回答 2

5

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

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

MichaelS 在 Oracle 论坛上有一个类似的,也许更简单的把戏,当然,我也不能把它归功于任何人。我很想在这里重现它,但我不确定这是否允许,但本质上它是sys_context用来维持计数的,这与 Adrian 的解决方案对包变量所做的方式大致相同。我会使用那个,因为它更干净,而且我认为它更容易遵循和维护。

仍然非常接近仅链接的答案,但我也不想抄袭别人的工作......

于 2013-10-03T10:41:11.640 回答
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;

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

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

于 2013-10-03T12:18:13.480 回答