ORA-01407: 无法更新为 NULL 试图获取实际数字

ORA-01407: cannot update to NULL Trying to get actual number

我有一个触发器,该语句与日期值进行比较并减去它们。根据哪个数字更大,它将乘以不同的数字。这应该存储一个实际值,但目前它正在尝试存储一个我不想要的空值。

CREATE OR REPLACE TRIGGER BALANCE_FEE
BEFORE INSERT OR UPDATE OR DELETE ON CHARTERS
FOR EACH ROW 
DECLARE
FEE NUMBER;
ACL_DATE DATE;
EXP_DATE DATE;
GRP_ID VARCHAR2(20);

BEGIN

ACL_DATE := :NEW.ACL_RETURN_DATE;
EXP_DATE := :NEW.EXP_RETURN_DATE;
GRP_ID := :NEW.GRP_ID;


IF ACL_DATE > EXP_DATE
THEN
FEE := ((ACL_DATE - EXP_DATE) * 75);

IF ACL_DATE < EXP_DATE
THEN
FEE := ((ACL_DATE - EXP_DATE)* -20);

END IF;
END IF;
UPDATE CUSTOMER
     SET CUSTOMER.BALANCE = CUSTOMER.BALANCE + FEE
     WHERE CUSTOMER.GRP_ID = GRP_ID;
END;
/
SHOW ERROR;

触发器中使用的表。

CREATE TABLE CUSTOMER (
    CUS_FNAME VARCHAR(20) NOT NULL,
    CUS_LNAME VARCHAR(20) NOT NULL,
    GENDER VARCHAR(20) NOT NULL,
    PHONENUM NUMBER(10) NOT NULL,
    CITY VARCHAR(20) NOT NULL,
    PARTY_COUNT INT NOT NULL,
    GRP_ID VARCHAR(20) NOT NULL PRIMARY KEY,
    CAN_RENT VARCHAR(20),
    BALANCE NUMBER NOT NULL);

CREATE TABLE CHARTERS (
    CHARTER_ID VARCHAR(20) NOT NULL,
    BOAT_ID VARCHAR(20) NOT NULL REFERENCES BOAT(BOAT_ID),
    GRP_ID VARCHAR(20) NOT NULL REFERENCES CUSTOMER(GRP_ID),
    EXP_RETURN_DATE DATE NOT NULL,
    ACL_RETURN_DATE DATE NOT NULL);

我遇到了这个错误

INSERT INTO CHARTERS (CHARTER_ID,BOAT_ID,EXP_RETURN_DATE,ACL_RETURN_DATE,GRP_ID) VALUES ('T002','B002',TO_DATE ('2019/03/10', 'yyyy/mm/dd'),TO_DATE ('2019/03/08', 'yyyy/mm/dd'),'G001')
Error report -
ORA-01407: cannot update ("ADMIN_BF"."CUSTOMER"."BALANCE") to NULL
ORA-06512: at "ADMIN_BF.BALANCE_FEE", line 24
ORA-04088: error during execution of trigger 'ADMIN_BF.BALANCE_FEE'

当运行使用这些插入语句时,我收到错误

INSERT INTO CHARTERS (CHARTER_ID,BOAT_ID,EXP_RETURN_DATE,ACL_RETURN_DATE,GRP_ID) VALUES ('T002','B002',TO_DATE ('2019/03/10', 'yyyy/mm/dd'),TO_DATE ('2019/03/08', 'yyyy/mm/dd'),'G001');

INSERT INTO CHARTERS (CHARTER_ID,BOAT_ID,EXP_RETURN_DATE,ACL_RETURN_DATE,GRP_ID) VALUES ('T001','B001',TO_DATE ('2019/01/20', 'yyyy/mm/dd'),TO_DATE ('2019/01/20', 'yyyy/mm/dd'),'G002');

当我运行这条语句时我没有得到错误

INSERT INTO CHARTERS (CHARTER_ID,BOAT_ID,EXP_RETURN_DATE,ACL_RETURN_DATE,GRP_ID) VALUES ('T003','B003',TO_DATE ('2019/05/05', 'yyyy/mm/dd'),TO_DATE ('2019/05/07', 'yyyy/mm/dd'),'G003');

您已经嵌套了第二个 if,这样只有当第一个计算结果为 true:

时才会对其进行计算
IF ACL_DATE > EXP_DATE
THEN
FEE := ((ACL_DATE - EXP_DATE) * 75);

IF ACL_DATE < EXP_DATE
THEN
FEE := ((ACL_DATE - EXP_DATE)* -20);

END IF;
END IF;

您可能想要 ELSIF:

IF ACL_DATE > EXP_DATE
THEN
FEE := ((ACL_DATE - EXP_DATE) * 75);

ELSIF ACL_DATE < EXP_DATE
THEN
FEE := ((ACL_DATE - EXP_DATE)* -20);

END IF;

但是如果您还需要考虑两个日期是否相等:

IF ACL_DATE > EXP_DATE
THEN
FEE := ((ACL_DATE - EXP_DATE) * 75);

ELSIF ACL_DATE < EXP_DATE
THEN
FEE := ((ACL_DATE - EXP_DATE)* -20);
else
fee := 0; --maybe

END IF;

在您的 trigger 中,您缺少相等条件。

您的触发器代码中有 IF ACL_DATE > EXP_DATEIF ACL_DATE < EXP_DATE,但如果 ACL_DATE = EXP_DATE 不满足任何 IF 条件,Fee 将为空。

所以 FEE 将为空,因为您甚至还没有初始化它并且

CUSTOMER.BALANCE + FEE(which is null) --> results in null

CUSTOMER.BALANCE 没有违反空约束。

最好的解决方案是用一些初始值 (0) 初始化 FEE 变量。

...
...
FOR EACH ROW 
DECLARE
FEE NUMBER := 0; -- this
ACL_DATE DATE;
EXP_DATE DATE;
...
...