如何在Oracle PL/SQL中实现AFTER INSERT Trigger?
How to implement AFTER INSERT Trigger in Oracle PL/SQL?
我正在尝试在 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;
这是 table 本身:
create table BLATABLE
(
ID NUMBER(19) not null primary key,
CLIENTID NUMBER(10),
CREATED TIMESTAMP(6),
STATUS VARCHAR2(255 char)
);
通过删除 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;
/
哪里
- SELECT 语句需要从
IF .. THEN
条件语句 中删除
- 最有可能的是,变异 table 错误会在行级触发器情况下引发
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.
不需要触发器。看起来一个简单的唯一约束应该在这里完成工作:
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)
);
唯一约束可防止在整个 table 中 (clientid, status)
出现重复。如果 DML 操作(插入、更新)尝试生成副本,则会引发错误并回滚操作。
如果在另一端,您希望每个用户只允许一个“待定”状态,那么您可以使用如下唯一索引:
create unique index bla_index
on blatable( (case when status = 'PENDING' then clientid end) );
我正在尝试在 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;
这是 table 本身:
create table BLATABLE
(
ID NUMBER(19) not null primary key,
CLIENTID NUMBER(10),
CREATED TIMESTAMP(6),
STATUS VARCHAR2(255 char)
);
通过删除 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;
/
哪里
- SELECT 语句需要从
IF .. THEN
条件语句 中删除
- 最有可能的是,变异 table 错误会在行级触发器情况下引发
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.
不需要触发器。看起来一个简单的唯一约束应该在这里完成工作:
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)
);
唯一约束可防止在整个 table 中 (clientid, status)
出现重复。如果 DML 操作(插入、更新)尝试生成副本,则会引发错误并回滚操作。
如果在另一端,您希望每个用户只允许一个“待定”状态,那么您可以使用如下唯一索引:
create unique index bla_index
on blatable( (case when status = 'PENDING' then clientid end) );