2012-01-07 33 views
2

我有一个语句级别的触发器,只要在一个表(称为客户)上执行INSERT UPDATE或DELETE操作时触发。我想显示一条消息(到DBMS_OUTPUT),其中包含插入/更新/删除的行数。如何在语句触发器中获取语句影响的行数

我只想为每个触发语句写一条消息,例如 '将4行插入customers表'中。

我如何可以访问从内部触发声明受触发语句的行数,即在XXX下面的代码:

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; 

无法找到文档中任何东西,任何帮助不胜感激!

+0

为什么最初你想要'dbms_output'吗?你会去那里检查每一次?此时用于调试的 – Ben 2012-01-07 14:37:02

+0

,稍后插入到表中。 – dav83 2012-01-07 14:39:20

+0

为什么不只是将触发器更改为'对于每一行'并插入到您的跟踪表中,然后有一个单独的查询来总结它们? – Ben 2012-01-07 15:18:23

回答

4

一种方法是使用全局变量来跟踪的行数,因为没有其他办法从语句级触发器获取行计数。然后,您需要三个触发器...一个语句级别在语句运行之前初始化该变量,一个行级别为每行添加一个变量,一个语句级别使用您希望的行数。首先,设置变量和一些程序,以帮助它:

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; 
/

第一个触发器初始化变量:

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

第二每行更新:

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; 
/

第三个显示总数:

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; 
+0

非常棒 - 非常感谢您的帮助! – dav83 2012-01-07 17:43:45

+1

在语句重新启动的情况下,这可能会导致错误的结果。如果行触发器是一个触发器之前,我会知道这是一个问题。作为一个触发后,我不知道重新启动是否有可能。有关语句重新启动的更多信息,请参阅:http://tkyte.blogspot.com/search?q=statement+restart – 2012-01-08 22:56:06

+0

自从引入了**复合触发器**的Oracle 11g以来,现在做起来要容易得多。在before语句中初始化一个rowCount变量。在每个行部分中,增加该变量。在声明部分之后,您可以访问该值。所以你不需要3个触发器,所有的逻辑都可以存在于一个复合触发器中。 – mancini0 2017-02-23 19:25:01

0

我不是100 $知道这是否是可用的内部AFTER触发的身体,但你可以尝试检查sql%rowcount

+0

谢谢 - 我试过这个,但唉,它只是NULL。 – dav83 2012-01-07 15:12:48