本节要点

设置表注释
设置默认值
设置主键
特殊的NULL值

设置表注释

这一节课是接着第3课来讲解的,都是关于创建表的相关内容。

在前面的课程中,我们讲过,在创建表时,对于表名和字段名,是不可以使用中文名的(虽然有的数据库也支持中文表名和中文字段名,但是我们并不建议这么做,因为很容易导致中文乱码的问题)。

可是,对于我们中国人来说,对中文是比较有感觉的,而对英文可能不太感冒,或者说不太容易记住。那如果表只有英文名,觉得不好记,怎么办呢?

其实,数据库为表提供了一个属性,叫COMMENT,也就是注释。这样,就可以为表设置一个中文注释(当然了,设置一个英文注释也是可以的),那么看起来就会顺眼很多。

为表设置注释,使用关键字:COMMENT,语法如下:

ALTER TABLE 表名 COMMENT '表注释';

比如,为teacher表添加注释”老师”:

ALTER TABLE teacher COMMENT '老师';

其实,在创建表时,就可以为表添加注释,比如下面这样:

CREATE TABLE teacher
(
    teacher_id VARCHAR(20),
    teacher_name VARCHAR(50),
    gender VARCHAR(10)
)COMMENT '老师';

另外,也可以为字段设置COMMENT,相关的内容我们后面再讲。

设置默认值

上面我们讲了,在创建一张表时,需要为表中的字段定义数据类型。这样在向表中插入数据时,就需要插入与对应位置字段的字段类型一致的数据,否则是会报错的。

但当我们插入数据的时候,并不想或并不需要对某个字段赋值时,如果字段有设置默认值,则会以默认值来填充该字段的值而不会导致错误;比如,在网上下订单时,对于下订单的日期字段,可以使用数据库的系统变量“当前日期”来默认赋值,这样就不需要在向订单表插入订单数据时,单独再对下订单的日期字段进行赋值。

再举个例子,我们在CSDN网站上注册一个新用户时,除了用户名、密码、手机号外,还有一些非必填信息,比如性别、QQ号、职业等。这些信息如果没有填写,那向数据库插入时,默认就会赋值为NULL值。

可如果性别、QQ号、职业等,这些字段被设置为NOT NULL,不可以插入NULL值,那怎么办呢?

同样,这个时候,就可以在创建表时,为字段设置默认值。

在向表中插入数据的时候,如果某个字段并没有指定赋值为多少,而此时该字段也没有赋默认值,那么就会向该字段插入NULL值。而NULL值的使用效率并不高,并且使用起来也比较麻烦。

所以,为避免字段的值被插入NULL值,一般在表创建时,都会为字段指定默认值。

设置默认值的关键字为DEFAULT,比如,像下面这样为老师姓名字段设置默认值”,为年龄字段设置默认值0,也就是空字段串:

CREATE TABLE teacher
(
    teacher_id VARCHAR(20),
    teacher_name VARCHAR(50) DEFAULT '',
    gender VARCHAR(10),
    age INT DEFAULT 0
)COMMENT '老师';

设置默认值需要关注以下几点:

表中所有的字段都可以设置默认值;
默认值的数据类型必须与字段类型保持一致;(不一致时,数据库虽然有时也会默认做隐式类型转换,但并不推荐这样做。一方面是这样做并不规范,另一方面是这样做可能会导致未知的错误)
除主键字段外,建议其他所有字段都设置默认值;

那一般根据什么来决定字段应该赋什么默认值呢?

对于字符型字段来说,一般赋值为空字符串(也就是”),或者具有某种业务含义的值。比如,对于性别字段,有三个取值,F-女,M-男,N-未知,当向这个性别字段插入数据时,可能并不知道性别是男还是女,那这时,就可以定义默认值为N-未知,代表我们并不知道这条数据记录的值到底是多少。

对于数值型字段来说,一般赋值为0,或者具有某种业务含义的值,或者该字段所表示的业务含义的最大值或极大值。

对于日期和时间型呢,常见的赋值有系统当前日期CURRENT_DATE、系统当前时间CURRENT_TIME、系统当前时间戳CURRENT_TIMESTAMP及NOW()等。

总的来说,我们都可以根据字段的业务含义来为字段赋默认值。

下面的表格列出了各个数据类型常见的默认值。

设置主键

先说一下什么是主键?

主键,是唯一标识表中每一行的某个列或多个列。

大家一定在记住这个定义,因为对于表中的所有字段来说,主键字段是最关键的。这也是我把主键单独作为一个章节来讲解的原因。以后大家在看到一张表时,其他字段都可以先不关注,首先看一下这张表的主键是什么。

因为主键表达了两方面的含义:

主键表示了表所描述的对象;
主键表示了表中数据的粒度;

什么叫表所描述的对象呢?

比如,对于学生表,它所描述的对象就是学生,而表中的主键就是唯一标识一个学生的学生编号。如果看到一张表的主键是学生编号,那基本可以肯定,这张表就是描述学生的属性的。

对于老师表也一样,它所描述的对象就是老师,表中的主键字段就是唯一标识一个老师的老师编号。如果看到一张表的主键是老师编号,那基本可以肯定,这张表就是描述老师的属性的。

什么叫表中数据的粒度呢?

比如,对于考试成绩表,主键是学生编号+课程编号,它描述的是每一个学生对应的课程考了多少分,那么这张表的数据粒度就是学生+课程。

在SQL语言里,使用PRIMARY KEY关键字来定义一张表的主键。比如,为teacher表定义主键teacher_id:

CREATE TABLE teacher
(
    teacher_id VARCHAR(20),
    teacher_name VARCHAR(50),
    gender VARCHAR(10),
    primary key ( teacher_id )
);

主键具有以下特点:

一个表只能有一个主键;
一个表中的所有行,主键字段的值不允许重复;注意:当多个字段同时做组合主键时,不允许重复,指的是所有主键字段的值加起来不重复就可以,而不是说组合主键中的某单个字段的值不允许重复。比如,主键字段值(2017,1)与另一个值(2018,1),虽然第二个字段的值都是1,但这是两条不主键不重复的数据;
主键的作用是保证数据的唯一性和完整性;
主键字段可以为多个,甚至是表中所有字段一起做主键;多个字段一起做主键时,我们称为联合主键或重复主键;不过一般来说不应该超过5个,否则会影响操作性能;
允许为NULL的字段不能做主键字段;
主键不应包含动态变化的数据;所以,永远也不要更新主键字段的值;

特殊的NULL值

把NULL值拿出来说,也是因为在数据库中,NULL值是一个非常特殊的值。不注意的话,很容易犯错误。

在创建表时,对于表中的每个字段,可以指定字段是否必须包含值。对于不是必须包含值的字段,可以向字段中插入NULL值。

比如像下面这样,定义teacher_id和teacher_name这两个字段必须有值,而gender字段可以没有值。

CREATE TABLE teacher
(
    teacher_id VARCHAR(20) NOT NULL,
    teacher_name VARCHAR(50) NOT NULL,
    gender VARCHAR(10) NULL,
    primary key ( teacher_id )
);

每个字段,要么是NOT NULL,要么是可为NULL。如果不指定的话,默认的是可为NULL,也就是允许不包含值。

说了这么多,那么NULL值到底是什么呢?

其实,NULL值什么都不是!记住,是什么都不是,没有人知道NULL值是什么!

那为什么会在数据库中设计这样一个NULL值呢?是因为用它来表示一种”不知道“、”不确定“的状态。它既不等于0,也不等于空格’ ‘,更不等于空字符串”,甚至,它也不等于NULL。

想像一下,如果我们不知道张三的年龄,那么可以将张三的年龄赋值为NULL,而同样的,我们也不知道李四的年龄,那么也可以将李四的年龄赋值为NULL。这个时候如果问,张三的年龄与李四的年龄一样吗?那肯定是一个无法回答的问题。这样去理解NULL值与NULL值不相等,是不是容易多了。

那既然NULL值跟什么都不相等,我们如何去判断一个字段的值为NULL值呢?

可以使用如下语句来判断:

gender is null; --判断gender字段为null值
gender is not null; --判断gender字段不为null值

使用gender = null;这样的判断方式是错误的!

其实,NULL值在数据库中的作用还是蛮大的。举个例子,一次期中考试过后,学校要对进步比较大的同学进行奖励。对于上学期期末考试总成绩在300分以下的同学,如果这次期中考试总成绩在500分以上,则发放200元奖学金;在400-500分之间,则发放100元奖学金;在400分以下,则发放0元奖学金,也就是不奖励。

画出表格如下:

那么上面这种描述,对上学期期末考试总成绩在300分以上的同学如何奖励并没有说明。此时,我们就可以为奖学金字段赋值为NULL,表示这个时候,我们还不知道学校如何对这部分学生进行奖励。

鉴于NULL值的特殊性,在使用NULL值时,我给出了下面两点忠告供大家参考:

允许NULL值的字段,不能作为主键字段;
尽量避免将字段设置为可为NULL,事实上,应该定下规范,所有字段都必须设置为NOT NULL;

picture loss