CREATE OR REPLACE TRIGGER trg_addRentalCollection
AFTER INSERT ON contracts
FOR EACH ROW
DECLARE
v_monthly_payment_date Date := :NEW.contractStartDate;
v_partial_payment NUMBER(9,2);
v_monthlyRentalFee Number(9,2);
BEGIN
SELECT monthlyRentalFee
INTO v_monthlyRentalFee
FROM stalls
WHERE stallID = :NEW.stallID;
FOR payment_rec IN 1..CEIL(:NEW.contractMonths) LOOP
IF payment_rec = 1 THEN
v_partial_payment := v_monthlyRentalFee * (EXTRACT(DAY FROM LAST_DAY(:NEW.contractStartDate)) - EXTRACT(DAY FROM :NEW.contractStartDate) + 1) / EXTRACT(DAY FROM LAST_DAY(:NEW.contractStartDate));
ELSE
v_partial_payment := 0;
END IF;
INSERT INTO rentalcollection VALUES ('RC' || TO_CHAR(rentalCollection_sequence.nextVal, 'FM00000'),:NEW.contractID, :NEW.renterID, :NEW.stallID, NULL, v_partial_payment + v_monthlyRentalFee, v_monthly_payment_date, 0, 'Unpaid');
v_monthly_payment_date := ADD_MONTHS(:NEW.contractStartDate, payment_rec);
END LOOP;
END;
/
CREATE TABLE contracts
(
contractID VARCHAR(15) NOT NULL, --C00001
renterID VARCHAR(15) NOT NULL,
stallID VARCHAR(15) NOT NULL,
ContractStartDate DATE,
ContractEndDate DATE,
contractMonths NUMBER(9,2),
totalContractFee NUMBER (9,2),
unpaidFee NUMBER (9,2),
status VARCHAR(11),
PRIMARY KEY (contractID, renterID, stallID),
FOREIGN KEY (renterID) REFERENCES renters(renterID),
FOREIGN KEY (stallID) REFERENCES stalls(stallID)
);
CREATE TABLE rentalcollection
(
rentalCollectionID VARCHAR(15) NOT NULL,
contractID VARCHAR(15) NOT NULL,
renterID VARCHAR(15) NOT NULL,
stallID VARCHAR(15) NOT NULL,
rentalCollectionDate DATE,
amount NUMBER(9,2),
actualCollectionDate DATE,
overdueFee NUMBER(9,2),
collectionStatus VARCHAR(15) DEFAULT 'Unpaid', --paid or unpaid
PRIMARY KEY (rentalCollectionID),
FOREIGN KEY (contractID, renterID, stallID) REFERENCES contracts(contractID, renterID, stallID)
);
这是一条插入后记录,用于为
rentalcollection
插入多个插入,但即使创建时没有触发错误,也没有插入任何行到 rentalcollection
表中。
当
rentalcollection
表中有 1 个插入时,此代码预计会向 contracts
表中插入多个条目。
...但是没有记录插入到rentalcollection表中
那是因为
stalls
表中没有匹配的行,或者您输入了 contractMonths
这会阻止循环至少运行一次。
这是一个工作演示。首先,您发布的表(我删除了我没有的表的外键约束):
SQL> CREATE TABLE contracts(
2 contractID VARCHAR(15) NOT NULL, --C00001
3 renterID VARCHAR(15) NOT NULL,
4 stallID VARCHAR(15) NOT NULL,
5 ContractStartDate DATE,
6 ContractEndDate DATE,
7 contractMonths NUMBER(9,2),
8 totalContractFee NUMBER (9,2),
9 unpaidFee NUMBER (9,2),
10 status VARCHAR(11),
11 PRIMARY KEY (contractID,renterID, stallID)
12 --FOREIGN KEY (renterID) REFERENCES renters(renterID),
13 --FOREIGN KEY (stallID) REFERENCES stalls(stallID)
14 );
Table created.
SQL> CREATE TABLE rentalcollection(
2 rentalCollectionID VARCHAR(15) NOT NULL,
3 contractID VARCHAR(15) NOT NULL,
4 renterID VARCHAR(15) NOT NULL,
5 stallID VARCHAR(15) NOT NULL,
6 rentalCollectionDate DATE,
7 amount NUMBER(9,2),
8 actualCollectionDate DATE,
9 overdueFee NUMBER(9,2),
10 collectionStatus VARCHAR(15) DEFAULT 'Unpaid', --paid or unpaid
11 PRIMARY KEY (rentalCollectionID),
12 FOREIGN KEY (contractID, renterID, stallID) REFERENCES contracts(contractID, renterID, stallID)
13 );
Table created.
我丢失了档位表和顺序;如果我想要触发器编译,我需要那个:
SQL> create table stalls as select 100 monthlyrentalfee, 1 stallid from dual;
Table created.
SQL> create sequence rentalCollection_sequence;
Sequence created.
触发;我没有修改任何东西:
SQL> CREATE OR REPLACE TRIGGER trg_addRentalCollection
2 AFTER INSERT ON contracts
3 FOR EACH ROW
4
5 DECLARE
6 v_monthly_payment_date Date := :NEW.contractStartDate;
7 v_partial_payment NUMBER(9,2);
8 v_monthlyRentalFee Number(9,2);
9
10 BEGIN
11
12 SELECT monthlyRentalFee
13 INTO v_monthlyRentalFee
14 FROM stalls
15 WHERE stallID = :NEW.stallID;
16
17 FOR payment_rec IN 1..CEIL(:NEW.contractMonths) LOOP
18 IF payment_rec = 1 THEN
19 v_partial_payment := v_monthlyRentalFee * (EXTRACT(DAY FROM LAST_DAY(:NEW.contractStartDate)) - EXTRACT(DAY FROM :NEW.contractStartDate) + 1) / EXTRACT(DAY FROM LAST_DAY(:NEW.contractStartDate));
20 ELSE
21 v_partial_payment := 0;
22 END IF;
23
24 INSERT INTO rentalcollection VALUES ('RC' || TO_CHAR(rentalCollection_sequence.nextVal, 'FM00000'),:NEW.contractID, :NEW.renterID, :NEW.stallID, NULL, v_partial_payment + v_monthlyRentalFee, v_monthly_payment_date, 0, 'Unpaid');
25
26
27 v_monthly_payment_date := ADD_MONTHS(:NEW.contractStartDate, payment_rec);
28
29 END LOOP;
30
31 END;
32 /
Trigger created.
好的,我们来测试一下。插入
contracts
:
SQL> insert into contracts values
2 ('a', 'b', '1', sysdate, sysdate + 2, 2, 1000, 300, 'x');
1 row created.
您期望
rentalcollection
中有一些行。我有两个,这意味着触发器似乎没问题(如果您在其他地方有正确的数据):
SQL> select * From rentalcollection;
RENTALCOLLECTIO CONTRACTID RENTERID STALLID RENTALCOL AMOUNT ACTUALCOL OVERDUEFEE COLLECTIONSTATU
--------------- ---------- -------- ------- --------- ---------- --------- ---------- ---------------
RC00001 a b 1 125.81 24-DEC-23 0 Unpaid
RC00002 a b 1 100 24-JAN-24 0 Unpaid
SQL>