如何解决处理 ORA-01403:触发器中没有发现异常的数据
我有两张桌子:
CREATE TABLE Patient
(
p_Name VARCHAR2(20) NOT NULL,p_Surname VARCHAR2(20) NOT NULL,idP INTEGER,b_Date DATE NOT NULL,d_Date DATE DEFAULT NULL,CONSTRAINT PK_idP PRIMARY KEY(idP)
);
CREATE TABLE Visit
(
idV INTEGER,date_V DATE NOT NULL,v_Hospital INTEGER NOT NULL,id_PV INTEGER,CONSTRAINT PK_idV PRIMARY KEY(idV),CONSTRAINT FK_idPV FOREIGN KEY(id_PV) REFERENCES Patient(idp)
ON DELETE CASCADE,CONSTRAINT FK_idHV FOREIGN KEY(v_Hospital) REFERENCES Hospital(idH)
ON DELETE CASCADE
);
我创建了一个触发器,这样当我在表 Visit 中插入一行时,如果患者已故(当然),它不应该允许我这样做,这就是它背后的逻辑。
CREATE OR REPLACE TRIGGER visitDeceased
BEFORE INSERT ON Visit
FOR EACH ROW
DECLARE
pd Patient.d_date%TYPE;
BEGIN
SELECT P.d_date INTO pd
FROM Patient P JOIN Visit V ON P.idP=:NEW.id_PV;
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO Visit(date_V,v_Hospital,id_PV) VALUES(:NEW.date_V,:NEW.v_Hospital,:NEW.id_PV);
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20111,'Error. Patient deceased.');
END;
/
问题是当 d_date 为 NULL 时,代码会生成 ORA-01403: no data found 错误。我正在尝试使用该异常处理它,但不起作用。有人知道如何使它工作吗?非常感谢。
解决方法
如果您希望一行匹配并且可以使用 NULL
值来处理不匹配,那么我发现聚合很方便:
SELECT MAX(P.d_date) INTO pd
FROM Patient P JOIN
Visit V
ON P.idP = :NEW.id_PV;
但是,在您的代码中,我只会使用 INSERT . . . SELECT
:
INSERT INTO Visit (date_V,v_Hospital,id_PV) V.
SELECT :NEW.date_V,:NEW.v_Hospital,:NEW.id_PV
FROM dual
WHERE NOT EXISTS (SELECT 1
FROM Patient p
WHERE p.idP = :NEW.id_PV
);
出于法律原因,您可能必须将已故患者从 Patient
中移除。但是,如果这不是必需的,我建议改用标志或 deceased_date
。
此外,可以通过使用外键约束来避免这个问题。这将验证关系完整性,而无需依赖触发器。
,希望,我正确理解了您的问题。
NO_DATA_FOUND
在 SELECT P.d_date INTO pd FROM Patient P JOIN Visit V ON P.idP=:NEW.id_PV;
不返回任何行时处理异常。当此查询存在行时,它不会处理,但是,d_date
为空。根据您的表结构 d_Date DATE DEFAULT NULL
,这是可能的。您可以通过以下方式处理:
*在 pd
查询后检查 select
是否为空。
例如:
IF pd IS NULL THEN
-- do your work
END IF;
OR
*在下面的查询中添加一个检查 where P.d_date is not null
。
SELECT P.d_date INTO pd FROM Patient P JOIN Visit V ON P.idP=:NEW.id_PV where P.d_date is not null;
当您在 VISIT 表上的 insert 语句上运行触发器时,为什么要在其中使用 Insert 语句?只需删除您的 Insert 语句,然后它就可以工作了 -
CREATE OR REPLACE TRIGGER visitDeceased
BEFORE INSERT ON Visit
FOR EACH ROW
DECLARE
pd Patient.d_date%TYPE;
BEGIN
SELECT P.d_date INTO pd
FROM Patient P JOIN Visit V ON P.idP=:NEW.id_PV;
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20111,'Error. Patient deceased.');
END;
/
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。