简体   繁体   中英

How to implement AFTER INSERT Trigger in Oracle PL/SQL?

I am trying to implement after insert trigger in PLSQL.
The goal is to check if there are multiple (>1) rows having specific status for each client.
If so I'd like to rise an exception and roll the insertion back.

I am struggling with implementing warning-free query, which causes error during insertion.
How could I manage this?
Here is my implemented trigger which I guess needs some changes.

CREATE TRIGGER blatrigger
    AFTER INSERT
    ON BLATABLE
    REFERENCING NEW AS NEW OLD AS OLD
    FOR EACH ROW
DECLARE
    exception_name EXCEPTION;
    PRAGMA EXCEPTION_INIT (exception_name, -20999);
BEGIN
    if (select count(*) as counter from BLATABLE where CLIENTID = :NEW.CLIENTID and STATUS='PENDING').counter > 1
    THEN
        raise exception_name;
    END IF;
END;

Here is the table itself:

create table BLATABLE
(
    ID            NUMBER(19) not null primary key,
    CLIENTID     NUMBER(10),
    CREATED       TIMESTAMP(6),
    STATUS        VARCHAR2(255 char)
);

The goal is to check if there are multiple (>1) rows having specific status for each client. If so I'd like to rise an exception and roll the insertion back.

No need for a trigger. It looks like a simple unique constraint should get the job done here:

create table blatable (
    id            number(19) not null primary key,
    clientid      number(10),
    created       timestamp(6),
    status        varchar2(255 char),
    constraint blaconstraint unique (clientid, status)
);

The unique constraint prevents duplicates on (clientid, status) across the whole table. If a DML operation (insert, update) attempts to generate a duplicate, an error is raised and the operation is rolled back.

If, on the other end, you want to allow only one "PENDING" status per user, then you can use a unique index as follows:

create unique index bla_index
    on blatable( (case when status = 'PENDING' then clientid end) );

Use a Statement Level Trigger, rather than a Row Level by removing FOR EACH ROW , and converting to your code as below :

CREATE OR REPLACE TRIGGER blatrigger
  AFTER INSERT ON BLATABLE
  REFERENCING NEW AS NEW OLD AS OLD

DECLARE
  counter        INT;
  exception_name EXCEPTION;
  PRAGMA EXCEPTION_INIT(exception_name, -20999);
BEGIN
  SELECT MAX(COUNT(*))
    INTO counter
    FROM BLATABLE
   WHERE STATUS = 'PENDING'
   GROUP BY CLIENTID;
     
  IF counter > 1 THEN
    RAISE exception_name;
  END IF;
END;
/

where

  • the SELECT statement need to be removed from IF .. THEN conditional
  • Most probably, the mutating table error would raise for Row Level Trigger case

Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM