如何在Oracle PL/SQL中实现AFTER INSERT触发器?

问题描述 投票:0回答:2

我正在尝试在 PLSQL 中实现插入后触发器。
目标是检查每个客户端是否有多个 (>1) 行具有特定状态。
如果是这样,我想引发异常并回滚插入。

我正在努力实现无警告查询,这会导致插入期间出错。
我该如何管理这个问题?
这是我实现的触发器,我想它需要一些更改。

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;

这是表格本身:

create table BLATABLE
(
    ID            NUMBER(19) not null primary key,
    CLIENTID      NUMBER(10),
    CREATED       TIMESTAMP(6),
    STATUS        VARCHAR2(255 char)
);
sql oracle plsql triggers sql-insert
2个回答
4
投票

目标是检查每个客户端是否有多个 (>1) 行具有特定状态。如果是这样,我想引发异常并回滚插入。

无需触发器。看起来一个简单的唯一约束应该可以在这里完成工作:

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

唯一约束可防止整个表中的

(clientid, status)
出现重复。如果 DML 操作(插入、更新)尝试生成重复项,则会引发错误并回滚操作。

另一方面,如果您只想允许每个用户有一个“PENDING”状态,那么您可以使用唯一索引,如下所示:

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

1
投票

通过删除

FOR EACH ROW
使用语句级触发器,而不是行级触发器,并转换为如下代码:

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

哪里

  • 需要从
    IF .. THEN
    条件
  • 中删除 SELECT 语句
  • 最有可能的是,行级别触发器情况下会引发变异表错误

演示

© www.soinside.com 2019 - 2024. All rights reserved.