如何添加数据库限制 - 检查约束或触发器

dRv*_*dRv 2 sql database oracle

我想知道如何在表上添加数据库限制.我想用Oracle数据库中的表简化问题

CREATE TABLE TEST_STUDENT
(

STUDENT VARCHAR2(30 CHAR),
SUBJECT VARCHAR2(38) ,
IS_LANG NUMBER(1,0)
);
Run Code Online (Sandbox Code Playgroud)

学生可以拥有任意数量的科目,但只有一门科目可以成为一种语言(IS_LANG).

有效数据将是

Insert into TEST_STUDENT (STUDENT,SUBJECT,IS_LANG) values ('John','Math',);
Insert into TEST_STUDENT (STUDENT,SUBJECT,IS_LANG) values ('John','Science',);
Insert into TEST_STUDENT (STUDENT,SUBJECT,IS_LANG) values ('John','French',1);
Insert into TEST_STUDENT (STUDENT,SUBJECT,IS_LANG) values ('Lily','Math',);
Insert into TEST_STUDENT (STUDENT,SUBJECT,IS_LANG) values ('Lily','English',1);
Run Code Online (Sandbox Code Playgroud)

但是,我不应该像表格一样插入新的数据

Insert into TEST_STUDENT (STUDENT,SUBJECT,IS_LANG) values ('John','English',1);
Run Code Online (Sandbox Code Playgroud)

要么

Insert into TEST_STUDENT (STUDENT,SUBJECT,IS_LANG) values ('Lily','French',1);
Run Code Online (Sandbox Code Playgroud)

我不想在这里引入触发器,除非它是唯一的方法.我希望有这个限制,因为在实际的软件中会有多个客户端实现尝试将数据插入到此表中.

a_h*_*ame 9

这是部分索引的一个很好的例子.

不幸的是,在Oracle中,您需要一种解决方法来实现部分索引(其他DBMS只允许WHERE应用子句):

create unique index idx_one_language 
   on test_student 
      (
          case when is_lang = 1 then student else null end
      );
Run Code Online (Sandbox Code Playgroud)

这利用了Oracle不会将所有列都为null的元组编入索引的事实.使用上面的表达式,只有IS_LANG = 1将为每个学生编制索引的行.由于索引被定义为唯一,因此只能存在一个这样的行.

这是一个SQLFiddle示例:http://sqlfiddle.com/#!4/43394d/1