Используйте материализованное представление с соответствующими ограничениями для проверки сложных требований, таких как это.
Например, давайте создадим таблицы и материализованное представление, добавим данные в таблицы и обновим sh MV :
CREATE TABLE PERSON ( -- SUPERTYPE
p_id NUMBER(2) CONSTRAINT c1 PRIMARY KEY,
name CHAR(15),
dob DATE
);
CREATE TABLE STUDENT ( -- SUBTYPE
s_id NUMBER(2) CONSTRAINT c2 PRIMARY KEY,
p_id_fk,
grade CHAR(1),
FOREIGN KEY (p_id_fk) REFERENCING PERSON (p_id)
);
CREATE TABLE TEACHER( -- SUBTYPE
t_id NUMBER(4) CONSTRAINT c3 PRIMARY KEY,
p_id_fk,
tel CHAR(8),
FOREIGN KEY (p_id_fk) REFERENCING PERSON (p_id)
);
CREATE MATERIALIZED VIEW PERSON_MV
REFRESH COMPLETE
AS SELECT p.P_ID,
s.S_ID,
t.T_ID
FROM PERSON p
LEFT OUTER JOIN STUDENT s
ON s.P_ID_FK = p.P_ID
LEFT OUTER JOIN TEACHER t
ON t.P_ID_FK = p.P_ID;
-- Add constraint to the table underlying the MV
ALTER MATERIALIZED VIEW PERSON_MV
ADD CONSTRAINT PERSON_MV_CK1
CHECK( (S_ID IS NULL AND -- either both are NULL
T_ID IS NULL) OR
( (S_ID IS NULL OR -- or only one is NULL
T_ID IS NULL) AND
(S_ID IS NOT NULL OR
T_ID IS NOT NULL)));
INSERT ALL
INTO PERSON (P_ID, NAME, DOB) VALUES (11, 'John', to_date('12/12/2012', 'dd/mm/yyyy'))
INTO PERSON (P_ID, NAME, DOB) VALUES (22, 'Maria', to_date('01/01/2001', 'dd/mm/yyyy'))
INTO PERSON (P_ID, NAME, DOB) VALUES (33, 'Philip', to_date('02/02/2002', 'dd/mm/yyyy'))
SELECT * FROM DUAL;
COMMIT;
INSERT INTO STUDENT VALUES (98, 11, 'A');
COMMIT;
BEGIN
DBMS_MVIEW.REFRESH('PERSON_MV', 'C', '', TRUE, FALSE, 0, 0, 0, FALSE, FALSE);
END;
/
SELECT *
FROM PERSON_MV;
Обратите внимание на ограничение, добавленное к материализованному представлению:
ALTER MATERIALIZED VIEW PERSON_MV
ADD CONSTRAINT PERSON_MV_CK1
CHECK( (S_ID IS NULL AND -- either both are NULL
T_ID IS NULL) OR
( (S_ID IS NULL OR -- or only one is NULL
T_ID IS NULL) AND
(S_ID IS NOT NULL OR
T_ID IS NOT NULL)));
Это ограничение позволяет существовать данным там, где:
- существует строка ЧЕЛОВЕКА, но не существует связанной строки STUDENT или TEACHER
- существует строка PERSON вместе с либо связанной строкой STUDENT или TEACHER, но не обе
Так что, когда мы выполнить последний SELECT из материализованного представления, которое мы получим:
P_ID S_ID T_ID
11 98 -
33 - -
22 - -
Теперь давайте изменим скрипт выше, добавив следующее сразу после INSERT INTO STUDENT
:
INSERT INTO TEACHER VALUES (1234, 11, 14809510);
COMMIT;
Если мы повторно запустив весь сценарий, мы обнаружим, что когда DBMS_MVIEW.REFRE SH вызывается для рефракции sh материализованного представления, мы получаем:
ORA-12008: error in materialized view or zonemap refresh path ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 3012
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 2424
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 88
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 253
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 2405
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 2968
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 3255
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 3287
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 16
ORA-06512: at line 2
ORA-06512: at "SYS.DBMS_SQL", line 1721
Это довольно длинный путь Oracle к сказать, что ограничение было нарушено. * 102 9 *
Смотрите этот Live SQL Oracle сеанс