1.5.2 如何在创建表时指定约束

约束可以在创建表的同时指定,也可以在表创建之后再指定。如果与表同时创建,那么在创建表的CREATE语句中通过CONSTRAINT关键字指定约束的名称和约束类型。同时创建表和约束的CREATE语句格式为:


CREATE TABLE表名(

列1 数据类型 CONSTRAINT 约束名1 约束类型,

列2 数据类型 CONSTRAINT 约束名2 约束类型,

……

);


其中约束名是为约束指定的唯一的名称。约束名可以由用户自己指定,也可以自动产生。如果省略关键字CONSTRAINT和约束名称,那么约束名称将自动产生。如果约束名称是自动产生的,那么根据这样的名称无法判断约束所在的表以及约束类型。如果用户自己指定约束名称,则可以在名称中包含表名、约束类型等有用信息。

如果在一个列的定义之后指定该列上的约束时,这种定义约束的方法称为列级约束。例如,下面的CREATE语句用来创建一个表,名为student,在各个列上都指定了约束。


SQL>CREATE TABLE student(

sno number(8)PRIMARY KEY,

sname char(8)NOT NULL,

gender char(2)CHECK(gender in('男','女')),

birthday date,

school varchar(40));


在创建表student时指定了三个约束,第一个约束指定学号sno列为主键,第二个约束指定姓名sname列不为空,第三个约束指定性别gender列的值只能是“男”或“女”,这些约束都是列级约束。在创建表时没有为这几个约束指定名字,系统将自动为它们指定各自的名字。下面的CREATE语句在创建表时指定约束,并为每个约束指定了名字。


SQL>CREATE TABLE student(

sno number(8)CONSTRAINT pk_sno PRIMARY KEY,

sname char(8)CONSTRAINT nn_sname NOT NULL,

gender char(2)CONSTRAINT gen_check CHECK(gender in('男','女')),

birthday date,

school varchar(40));


约束可以在每个列的定义之后分别指定,也可以在所有列的定义之后一起指定。如果一个约束在表定义的最后才指定,这样的约束定义方法称为表级约束。如果一个约束涉及多个列的组合,那么就不能在每个列之后指定约束,而只能定义为表级约束。例如,若表student的主键列不是sno列,而是sno列和sname列的组合,这样的约束就不能在sno列或sname列之后指定,而只能在所有列的定义之后再指定。定义表级约束的CREATE语句格式为:


CREATE TABLE 表名(

列1 数据类型,

列2 数据类型,

……

CONSTRAINT 约束名1 约束类型(列名),

CONSTRAINT 约束名2 约束类型(列名),

……);


在五种约束中,NOT NULL约束只能以列级约束的形式定义,其余四种既可以以列级约束的形式定义,也可以以表级约束的形式定义。因为表级约束是在所有列之后定义的,而不是在某个具体的列之后定义,所以在表级约束中要指定相关的列名。

例如,上面的创建表的CREATE语句也可以改为下面的形式:


CREATE TABLE student(

sno number(8),

sname char(8)CONSTRAINT nn_sname NOT NULL,

gender char(2),

birthday date,

school varchar(40),

CONSTRAINT pk_sno PRIMARY KEY(sno),

CONSTRAINT gen_check CHECK(gender in('男','女'))

);


外键约束的定义形式比较复杂,因为外键要与另一个表的主键进行关联,所以不仅要指定约束的类型和有关的列,还要指定与哪个表的哪个列进行关联。

如果在列级定义外键约束,定义的格式为:


CONSTRAINT约束名REFERENCES表名(列名)


其中约束名是为这个外键约束起的名字。FOREIGN KEY为约束类型,即外键约束。REFERENCES关键字指定与哪个表的哪个列进行关联。例如,在表emp中,外键列为deptno,它与表dept的deptno列进行关联。这个外键的定义语句为:


CONSTRAINT fk_deptno REFERENCES dept(deptno)


这条代码放置在emp表的deptno列定义之后。如果要在表级定义外键约束,那么外键的定义代码放置在所有列的定义之后,它的格式为:


CONSTRAINT约束名FOREIGN KEY(外键列)REFERENCES表名(列名)


例如,在表emp中的deptno列上施加的外键约束也可以通过下面的形式定义:


CONSTRAINT fk_deptno FOREIGN KEY(deptno)REFERENCES dept(deptno)


约束作为一种附加在表上的数据库对象,它的信息也被记录在数据字典中。与约束有关的数据字典有两个,一个是user_constraints;另一个是user_cons_columns。其中在数据字典user_constraints中记录当前用户所拥有的约束的信息,如约束名、约束类型、约束所在的表、约束的状态等。如果是外键,还记录了与之关联的主键名称。例如,下面的SELECT语句用来查询表student上的约束信息:


SQL>SELECT constraint_name AS名称,constraint_type AS约束类型,status AS状态

FROM user_constraints

WHERE table_name='STUDENT';


这条SELECT语句的执行结果为:


约束名 约束类型 状态

NN_SNAME C ENABLED

GEN_CHECK C ENABLED

PK_SNO P ENABLED


如果要进一步查询约束施加在哪个列上,就需要查询另一个数据字典了,它就是USER_CONS_COLUMNS。例如,下面的SELECT语句查询表student中的各个约束是在哪个列上定义的:


SQL>SELECT constraint_name, table_name, column_name

FROM user_cons_columns WHERE table_name='STUDENT';


这条SELECT语句的执行结果为:


CONSTRAINT_NAME TABLE_NAME COLUMN_NAME

NN_SNAME STUDENT SNAME

PK_SNO STUDENT SNO

GEN_CHECK STUDENT GENDER