[primary在其他表上使用时如何防止在表中输入值?

问题描述 投票:0回答:2

我必须构造并填充超类型-子类型关系,但是我无法使其按预期的方式工作。基本上PERSON表是表STUDENTTEACHER(子类型)的超类型。但是一个人可以是学生,也可以是老师。

属性:

PERSON(p_id,name,dob)

学生(s_id,p_id,成绩)

TEACHER(t_id,p_id,tel)


学生和老师都应该具有名称和DOB以及p_id作为外键,但如果它存在于一个表中,则不应位于另一个表上

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)
);

INSERT INTO PERSON VALUES (11, 'John', to_date('12/12/12', 'dd/mm/yy'));
INSERT INTO PERSON VALUES (22, 'Maria', to_date('01/01/01', 'dd/mm/yy'));
INSERT INTO PERSON VALUES (33, 'Philip', to_date('02/02/02', 'dd/mm/yy'));

INSERT INTO STUDENT VALUES (98, 11, 'A');

INSERT INTO TEACHER VALUES (1234, 11, 14809510);

如何防止两个表中都存在11号人员(John)?] >>

我必须构造并填充超类型-子类型关系,但是我无法使其按预期的方式工作。基本上,PERSON表是表STUDENT和TEACHER(...]

一个选项是使用数据库触发器,每个表一个(STUDENTTEACHER);他们看起来一样:
STUDENT上触发:
SQL> create or replace trigger trg_bi_stu 2 before insert on student 3 for each row 4 declare 5 l_cnt number; 6 begin 7 -- inserting into STUDENT: check whether that person exists in TEACHER table 8 select count(*) 9 into l_cnt 10 from teacher 11 where p_id_fk = :new.p_id_fk; 12 13 if l_cnt > 0 then 14 raise_application_error(-20001, 'That person is a teacher; can not be a student'); 15 end if; 16 end; 17 / Trigger created.

TEACHER上触发:

SQL> create or replace trigger trg_bi_tea 2 before insert on teacher 3 for each row 4 declare 5 l_cnt number; 6 begin 7 -- inserting into TEACHER: check whether that person exists in STUDENT table 8 select count(*) 9 into l_cnt 10 from student 11 where p_id_fk = :new.p_id_fk; 12 13 if l_cnt > 0 then 14 raise_application_error(-20001, 'That person is a student; can not be a teacher'); 15 end if; 16 end; 17 / Trigger created. SQL>

测试:

SQL> INSERT INTO STUDENT VALUES (98, 11, 'A'); 1 row created. SQL> SQL> INSERT INTO TEACHER VALUES (1234, 11, 14809510); INSERT INTO TEACHER VALUES (1234, 11, 14809510) * ERROR at line 1: ORA-20001: That person is a student; can not be a teacher ORA-06512: at "SCOTT.TRG_BI_TEA", line 11 ORA-04088: error during execution of trigger 'SCOTT.TRG_BI_TEA' SQL>

存在
四种方式如何将继承映射到替代数据库。
前三个很好地记录在案,该page提供了有用的链接。

基本上可以映射

1)所有类在一个表中>

2)对所有具体类使用一个表

3)为aech类定义一个表

所有这些选项都由于过度连接或激活的约束而出现了一些问题(例如,您无法在选项1中定义不可为空的列,因此,对于选项4而言,是完全完成的)是

不要在关系数据库中使用无礼式

您已经尝试实现选项3),但是问题是所有表必须继承相同的主键(以实现1:1关系)。

这里是所有选项的ovverview

-- 1) single table CREATE TABLE PERSON ( p_id NUMBER(2) CONSTRAINT pers_pk PRIMARY KEY, name CHAR(15), dob DATE, grade CHAR(1), tel CHAR(8) ); -- 2) table per concrete class CREATE TABLE STUDENT ( p_id NUMBER(2) CONSTRAINT stud_pk PRIMARY KEY, name CHAR(15), dob DATE, grade CHAR(1) ); CREATE TABLE TEACHER( p_id NUMBER(2) CONSTRAINT tech_pk PRIMARY KEY, name CHAR(15), dob DATE, tel CHAR(8) ); -- 3) table per class CREATE TABLE PERSON ( p_id NUMBER(2) CONSTRAINT pers_pk PRIMARY KEY, name CHAR(15), dob DATE ); CREATE TABLE STUDENT ( p_id NUMBER(2) CONSTRAINT stud_pk PRIMARY KEY, grade CHAR(1), FOREIGN KEY (p_id) REFERENCING PERSON (p_id) ); CREATE TABLE TEACHER( p_id NUMBER(2) CONSTRAINT tech_pk PRIMARY KEY, tel CHAR(8), FOREIGN KEY (p_id) REFERENCING PERSON (p_id) ); INSERT INTO PERSON (P_ID, NAME, DOB) VALUES (11, 'John', to_date('12/12/12', 'dd/mm/yy')); INSERT INTO PERSON (P_ID, NAME, DOB) VALUES (22, 'Maria', to_date('01/01/01', 'dd/mm/yy')); INSERT INTO PERSON (P_ID, NAME, DOB) VALUES (33, 'Philip', to_date('02/02/02', 'dd/mm/yy')); INSERT INTO STUDENT (P_ID, GRADE) VALUES (11, 'A'); INSERT INTO TEACHER (P_ID, TEL) VALUES (11, 14809510);
sql oracle subtype supertype
2个回答
0
投票

0
投票
前三个很好地记录在案,该page提供了有用的链接。
© www.soinside.com 2019 - 2024. All rights reserved.