Tôi đồng ý với các nhận xét đã đăng rằng nó sẽ giúp có một số chi tiết cụ thể về những gì không thành công trong những lần thử trước và tôi cũng khuyên bạn không nên sử dụng TRIGGER
hoàn toàn cho loại điều này.
Nhưng vì đây là một bài tập nghiên cứu, đây là một số ví dụ có thể là điểm khởi đầu.
Tôi đã sửa đổi các bảng của bạn để không cho phép NULL
PRIMARY KEY
s trong các ví dụ này.
Để bắt đầu, hãy tạo các bảng:
CREATE TABLE CLIENTS (
CLIENTID VARCHAR2(15) NOT NULL,
DNI VARCHAR2(9),
NAME VARCHAR2(100) NOT NULL,
SURNAME VARCHAR2(100) NOT NULL,
SEC_SURNAME VARCHAR2(100),
EMAIL VARCHAR2(100) NOT NULL,
PHONEN NUMBER(12),
BIRTHDATE DATE,
CONSTRAINT PK_CLIENTS PRIMARY KEY (CLIENTID),
CONSTRAINT UK1_CLIENTS UNIQUE (DNI),
CONSTRAINT UK2_CLIENTS UNIQUE (EMAIL),
CONSTRAINT UK3_CLIENTS UNIQUE (PHONEN)
);
CREATE TABLE CONTRACTS (
CONTRACTID VARCHAR2(10) NOT NULL,
CLIENTID VARCHAR2(15) NOT NULL,
STARTDATE DATE NOT NULL,
ENDDATE DATE,
CONTRACT_TYPE VARCHAR2(50),
ADDRESS VARCHAR2(100) NOT NULL,
TOWN VARCHAR2(100) NOT NULL,
ZIPCODE VARCHAR2(8) NOT NULL,
COUNTRY VARCHAR2(100) NOT NULL,
CONSTRAINT PK_CONTRACTS PRIMARY KEY (CONTRACTID),
CONSTRAINT FK_CONTRACTS1 FOREIGN KEY (CLIENTID) REFERENCES CLIENTS
);
Sau đó, tạo CLIENT
đầu tiên s:
INSERT INTO CLIENTS VALUES (1,NULL,'Frodo','Baggins',NULL,'[email protected]',NULL,NULL);
INSERT INTO CLIENTS VALUES (2,NULL,'Chewbacca','UNKNOWN',NULL,'[email protected]',NULL,NULL);
COMMIT;
Sau đó, tạo TRIGGER
. Trong ví dụ đầu tiên này, TRIGGER
là một AFTER STATEMENT
loại.
Nó đơn giản nhưng không hiệu quả vì nó đánh giá mọi CLIENT
sau mỗi INSERT
câu lệnh.
Đối mặt với một tập dữ liệu lớn hoặc khi đối mặt với nhiều TRIGGER
s, đây có thể là sự cố.
TRIGGER
này sẽ kiểm tra hợp đồng trước và sẽ đặt ENDDATE
của nó đến một ngày trước hợp đồng mới, nếu nó vô hiệu hoặc sau khi bắt đầu hợp đồng mới.
CREATE OR REPLACE TRIGGER CONTRACT_ENDDATE_ADJUSTER
AFTER INSERT ON CONTRACTS
BEGIN
MERGE INTO CONTRACTS
USING (
SELECT CONTRACTID,
CANDIDATE_ENDDATE AS ENDDATE
FROM
(SELECT CONTRACTS.CONTRACTID,
(TRUNC(LEAD(STARTDATE) OVER (PARTITION BY CLIENTID ORDER BY STARTDATE ASC) - 1)) AS CANDIDATE_ENDDATE,
DENSE_RANK() OVER (PARTITION BY CLIENTID ORDER BY STARTDATE DESC) AS CONTRACT_ORDER
FROM CONTRACTS)
WHERE CONTRACT_ORDER = 2) CANDIDATE_CONTRACT
ON (CONTRACTS.CONTRACTID = CANDIDATE_CONTRACT.CONTRACTID)
WHEN MATCHED THEN UPDATE SET CONTRACTS.ENDDATE = CANDIDATE_CONTRACT.ENDDATE
WHERE CONTRACTS.ENDDATE IS NULL OR CONTRACTS.ENDDATE > CANDIDATE_CONTRACT.ENDDATE;
END;
/
Sau đó, hãy kiểm tra nó.
Thêm các hợp đồng ban đầu. Không có thay đổi ngày cuối cùng được mong đợi, vì đây là lần đầu tiên. Hợp đồng của Frodo ở đây đã có ngày kết thúc.
INSERT INTO CONTRACTS VALUES('Break-Ring',1,TO_DATE('19560511','YYYYMMDD'), TO_DATE('19851014','YYYYMMDD'), NULL, 'No 1', 'Doom Mountain', 'MORD', 'Middle-Earth');
INSERT INTO CONTRACTS VALUES('SaveGalaxy',2,TO_DATE('19770615','YYYYMMDD'), NULL, NULL, 'No 75', 'Rwookrrorro', 'RWKR', 'Kashyyyk');
SELECT CONTRACTID, CLIENTID, STARTDATE, ENDDATE FROM CONTRACTS ORDER BY CLIENTID ASC, STARTDATE ASC;
CONTRACTID CLIENTID STARTDATE ENDDATE
Break-Ring 1 11-MAY-56 14-OCT-85
SaveGalaxy 2 15-JUN-77
Sau đó, thêm các hợp đồng mới.
Hợp đồng mới của Frodo bắt đầu trước khi kết thúc hợp đồng hiện tại của anh ấy, vì vậy thời hạn kết thúc sẽ được điều chỉnh.
Hợp đồng ban đầu của Chewie không có ENDDATE, vì vậy nó cũng sẽ được điều chỉnh.
INSERT INTO CONTRACTS VALUES('GoBackHome',1,TO_DATE('19570219','YYYYMMDD'), NULL, NULL, 'No 13', 'Hobbiton', 'HBTN', 'Middle-Earth');
INSERT INTO CONTRACTS VALUES('DefendHoth',2,TO_DATE('19801115','YYYYMMDD'), NULL, NULL, 'Meteor Crater', 'Ice Ridge', 'METEO', 'Hoth');
SELECT CONTRACTID, CLIENTID, STARTDATE, ENDDATE FROM CONTRACTS ORDER BY CLIENTID ASC, STARTDATE ASC;
CONTRACTID CLIENTID STARTDATE ENDDATE
Break-Ring 1 11-MAY-56 18-FEB-57
GoBackHome 1 19-FEB-57
SaveGalaxy 2 15-JUN-77 14-NOV-80
DefendHoth 2 15-NOV-80
Và khi các hợp đồng khác được ký kết, mô hình tiếp tục:
INSERT INTO CONTRACTS VALUES('GoWedding',2,TO_DATE('19830309','YYYYMMDD'), NULL, NULL, 'Main Hall', 'Grand Palace', 'ALLNC', 'Coruscant');
INSERT INTO CONTRACTS VALUES('Gardening',1,TO_DATE('19570503','YYYYMMDD'), NULL, NULL, 'No 13', 'Hobbiton', 'HBTN', 'Middle-Earth');
SELECT CONTRACTID, CLIENTID, STARTDATE, ENDDATE FROM CONTRACTS ORDER BY CLIENTID ASC, STARTDATE ASC;
CONTRACTID CLIENTID STARTDATE ENDDATE
Break-Ring 1 11-MAY-56 18-FEB-57
GoBackHome 1 19-FEB-57 02-MAY-57
Gardening 1 03-MAY-57
SaveGalaxy 2 15-JUN-77 14-NOV-80
DefendHoth 2 15-NOV-80 08-MAR-83
GoWedding 2 09-MAR-83
Để ổn định khối lượng công việc trên truy vấn này, thay vào đó có thể sử dụng BỘ TRÍCH HỢP HỢP CHẤT. Ví dụ thứ hai này đạt được kết quả tương tự như ví dụ đầu tiên, nhưng chỉ thẩm vấn CONTRACT
s trong số CLIENT
s đã thay đổi:
Đầu tiên, ROLLBACK;
Sau đó, tạo một loại được sử dụng bởi TRIGGER
:
CREATE OR REPLACE TYPE NUMBER_LIST IS TABLE OF NUMBER;
/
Sau đó, tạo COMPOUND TRIGGER
:
CREATE OR REPLACE TRIGGER CONTRACT_ENDDATE_ADJUSTER
FOR INSERT ON CONTRACTS
COMPOUND TRIGGER
V_CLIENTS NUMBER_LIST;
BEFORE STATEMENT
IS
BEGIN
V_CLIENTS:= NUMBER_LIST();
END BEFORE STATEMENT;
AFTER EACH ROW
IS
BEGIN
V_CLIENTS.EXTEND();
V_CLIENTS(V_CLIENTS.COUNT) := :NEW.CLIENTID;
END AFTER EACH ROW;
AFTER STATEMENT IS
BEGIN
MERGE INTO CONTRACTS
USING (
SELECT CONTRACTID,
CANDIDATE_ENDDATE AS ENDDATE
FROM
(SELECT CONTRACTS.CONTRACTID,
(TRUNC(LEAD(STARTDATE) OVER (PARTITION BY CLIENTID ORDER BY STARTDATE ASC) - 1)) AS CANDIDATE_ENDDATE,
DENSE_RANK() OVER (PARTITION BY CLIENTID ORDER BY STARTDATE DESC) AS CONTRACT_ORDER
FROM CONTRACTS
WHERE CONTRACTS.CLIENTID IN (SELECT * FROM TABLE(V_CLIENTS)))
WHERE CONTRACT_ORDER = 2) CANDIDATE_CONTRACT
ON (CONTRACTS.CONTRACTID = CANDIDATE_CONTRACT.CONTRACTID)
WHEN MATCHED THEN UPDATE SET CONTRACTS.ENDDATE = CANDIDATE_CONTRACT.ENDDATE
WHERE CONTRACTS.ENDDATE IS NULL OR CONTRACTS.ENDDATE > CANDIDATE_CONTRACT.ENDDATE;
END AFTER STATEMENT;
END CONTRACT_ENDDATE_ADJUSTER;
/
Sau khi lặp lại các lần chèn trên, kết quả giống nhau:
CONTRACTID CLIENTID STARTDATE ENDDATE
Break-Ring 1 11-MAY-56 18-FEB-57
GoBackHome 1 19-FEB-57 02-MAY-57
Gardening 1 03-MAY-57
SaveGalaxy 2 15-JUN-77 14-NOV-80
DefendHoth 2 15-NOV-80 08-MAR-83
GoWedding 2 09-MAR-83