简体   繁体   English

避免插入的触发器问题(Oracle SQL)

[英]Problem with trigger for avoiding insert (Oracle SQL)

I'm trying to make a trigger to avoid inserting data in the table for this reason: If a patient is dead he can't make a visit.由于这个原因,我正在尝试制作一个触发器以避免在表中插入数据:如果患者已经死亡,他将无法访问。 I made a function that return a 1 if the patient is dead and I call it on the trigger.我做了一个函数,如果病人死了,它会返回一个 1,我在触发器上调用它。 That's the code:那是代码:

CREATE OR REPLACE FUNCTION check_d (pd INTEGER)
RETURN INTEGER
IS
d Patient.d_date%TYPE;
BEGIN
SELECT P.d_Date INTO d
FROM Patient P
WHERE P.idP=pd;
IF d <> NULL THEN
    RETURN 1;
ELSE
    RETURN 0;   
END IF;
END;

CREATE OR REPLACE TRIGGER bad_insert
BEFORE INSERT ON Visit
FOR EACH ROW
DECLARE
idd INTEGER;
dp  Visit.id_PV%TYPE;
BEGIN
SELECT V.id_PV INTO dp
FROM Visit V
WHERE id_PV=:NEW.id_PV;

idd := check_d(dp);
IF idd = 1 THEN
    RAISE_APPLICATION_ERROR(-20014,'Error. Patient Deceased.');
END IF;
END;
/

The function should be ok, the problem is in thet trigger.功能应该没问题,问题出在trigger上。 Visit.id_PV is a Foreign Key to Patient.idP(PRIMARY KEY) anyway.无论如何,Visit.id_PV 是 Patient.idP(PRIMARY KEY) 的外键。 How should I modify the code?我应该如何修改代码? Thanks.谢谢。

Your function is not correct你的功能不正确

d <> NULL 

Will always return UNKNOWN, instead you have to check for nulls like:将始终返回 UNKNOWN,而您必须检查空值,例如:

d is not null

Once you've fixed that, you still have to work around the mutating table error you'd receive when you try an insert statement (did you not receive this when you tried it?).一旦你解决了这个问题,你仍然需要解决你在尝试插入语句时收到的变异表错误(你在尝试时没有收到这个错误吗?)。 You are referencing the same table you are inserting into within your trigger.您正在引用您在触发器中插入的同一个表。 You can't do that.你不能那样做。 Instead you should reference the column you want using :new.id_PV .相反,您应该使用 :new.id_PV 引用您想要的列。

I think the problem is located here :我认为问题出在这里:

IF d <> NULL THEN

Change it to :将其更改为:

IF d IS NOT NULL THEN

In the current case, you'll get no_data_found exception because of the query within the trigger.在当前情况下,由于触发器中的查询,您将获得no_data_found异常。 Moreover, you do not need to return the value for id_PV column that you already have as :NEW.id_PV , and such attempt mostly end with mutating trigger error.此外,您不需要返回您已经拥有的id_PV列的值:NEW.id_PV ,并且这种尝试大多以mutating trigger错误结束。 So , rearrange your trigger as因此,将触发器重新排列为

CREATE OR REPLACE TRIGGER bad_insert
BEFORE INSERT ON Visit
FOR EACH ROW
BEGIN
  IF check_d(:NEW.id_PV) = 1 THEN
    RAISE_APPLICATION_ERROR(-20014, 'Error. Patient Deceased.');
  END IF;
END;
/

while getting rid of redundant local variables.同时摆脱多余的局部变量。

The function might also be made brief such as该功能也可以简短,例如

CREATE OR REPLACE FUNCTION check_d (pd Visit.id_PV%type) RETURN INT IS
 val INT;
BEGIN
 SELECT NVL(SUM(NVL2(P.d_Date,1,0)),0) 
   INTO val
   FROM Patient P
  WHERE P.idP=pd;
  
 RETURN val; 
END;
/

Demo 演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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