How to get number of rows affected by a statement when inside that statement's trigger

dav83 picture dav83 · Jan 7, 2012 · Viewed 9.3k times · Source

I have a statement level trigger that fires whenever INSERT UPDATE or DELETE operations are performed on a table (called customers). I want to display a message (to DBMS_OUTPUT) containing the number of rows that were inserted/updated/deleted.

I just want one message for each triggering statement, eg '4 rows were inserted into customers table'.

How can I access the number of rows that are affected by the triggering statement from INSIDE the trigger declaration, ie XXX in the code below:

CREATE OR REPLACE TRIGGER customer_changes_trigger_2
AFTER INSERT OR UPDATE OR DELETE ON customers

DECLARE
v_operation   VARCHAR(10);
v_number_rows NUMBER;


BEGIN

v_number := XXX;

IF INSERTING THEN
   v_operation := 'inserted';
END IF;

IF UPDATING THEN
   v_operation := 'updated';
END IF;

IF DELETING THEN
   v_operation := 'deleted';
END IF;

DBMS_OUTPUT.PUT_LINE
          (v_number_rows|| ' rows were ' || v_operation || ' from customers.');
END;

Can't find anything in the documentation, any help appreciated!

Answer

John Doyle picture John Doyle · Jan 7, 2012

One way is to use a global variable to track the number of rows as there is no other way to get the row count from a statement level trigger. You would then need three triggers... one statement level to initialise the variable before the statement is run, one row level to add one to the variable for each row, one statement level to use the row count however you wish. First, set up the variable and a few procedures to help it:

create or replace package PKG_ROWCOUNT is
  NUMROWS   number;

  procedure INIT_ROWCOUNT;

  procedure ADD_ONE;

  function GET_ROWCOUNT
    return number;
end PKG_ROWCOUNT;
/

create or replace package body PKG_ROWCOUNT as
  procedure INIT_ROWCOUNT is
  begin
    NUMROWS := 0;
  end;

  procedure ADD_ONE is
  begin
    NUMROWS := Nvl(NUMROWS, 0) + 1;
  end;

  function GET_ROWCOUNT
    return number is
  begin
    return NUMROWS;
  end;
end PKG_ROWCOUNT;
/

The first trigger to initialise the variable:

create or replace trigger CUSTOMER_CHANGES_TRIGGER_1
  before insert or update or delete
  on CUSTOMERS
begin
  PKG_ROWCOUNT.INIT_ROWCOUNT;
end;

The second to update per row:

create or replace trigger CUSTOMER_CHANGES_TRIGGER_2
  after insert or update or delete
  on CUSTOMERS
  for each row
begin
  PKG_ROWCOUNT.ADD_ONE;
end;
/

The third to display the total:

create or replace trigger CUSTOMER_CHANGES_TRIGGER_3
  after insert or update or delete
  on CUSTOMERS
begin
   Dbms_output.
   PUT_LINE(PKG_ROWCOUNT.GET_ROWCOUNT || ' rows were affected.');
end;