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