问题描述
我试图在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)
);
解决方法
目标是检查每个客户是否有多行(> 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) );
,
使用语句级触发器,而不是行级,方法是删除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语句 - 很可能在行级触发器的情况下会引起变异表错误