约束条件与数据类型的宽度一样,都是可选参数
作用:用于保证数据的完整性和一致性
主要分为: PRIMARY KEY (PK) 标识该字段为该表的主键,可以唯一的标识记录 FOREIGN KEY (FK) 标识该字段为该表的外键 NOT NULL 标识该字段不能为空 UNIQUE KEY (UK) 标识该字段的值是唯一的 AUTO_INCREMENT 标识该字段的值自动增长(整数类型,而且为主键) DEFAULT 为该字段设置默认值 UNSIGNED 无符号 ZEROFILL 使用0填充 说明: 1. 是否允许为空,默认NULL,可设置NOT NULL,字段不允许为空,必须赋值 2. 字段是否有默认值,缺省的默认值是NULL,如果插入记录时不给字段赋值,此字段使用默认值 sex enum('male','female') not null default 'male' age int unsigned NOT NULL default 20 必须为正值(无符号) 不允许为空 默认是20 3. 是否是key 主键 primary key 外键 foreign key 索引 (index,unique...)
从约束角度看primary key字段的值不为空且唯一
主键primary key是innodb存储引擎组织数据的依据,innodb称之为索引组织表,一张表中必须有且只有一个主键。
一个表中可以:
单列做主键
多列做主键(复合主键)
主键通常都是id字段:对于以后建的表都是innodb存储引擎的, 在建表的时候一定要有id,id一定得是主键 create table t3( id int primary key ); insert t3 values(1); 联合主键(了解) create table t5( id int, name varchar(10), primary key(id,name) ); insert t5 values(1,"egon"); -- 正常插入 insert t5 values(1,"tom"); -- 正常插入 insert t5 values(1,"egon"); -- 重复,报错
约束字段为自动增长,被约束的字段必须同时被key约束
create table t6( id int primary key auto_increment, name varchar(16) ); insert t6(name) values("geng"); -- 给name插入值 insert t6(name) values("yang"); -- 给name插入值 insert t6(name) values("sun"); -- 给name插入值
是否可空,null表示空,非字符串
not null - 不可空
null - 可空
default - 默认值,创建列时可以指定默认值,当插入数据时如果未主动设置,则自动添加默认值
create table t7( id int not null, name varchar(16) ); insert t7 values(null,"geng"); create table t8( id int not null default 0, name varchar(16) ); insert t8(name) values("geng");
unique设置唯一约束,不允许重复
create table t9( id int unique, name varchar(16) ); insert t9 values(1,"geng"); insert t9 values(1,"yang"); -- 报错id重复 补充知识:not null+unique的化学反应 create table t10( id int not null unique, name varchar(16) ); id 字段变成了主键:不为空且唯一 mysql> create table t10( -> id int not null unique, -> name varchar(16) -> ); Query OK, 0 rows affected (0.24 sec) mysql> desc t10; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(16) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 2 rows in set (0.02 sec)
员工信息表有三个字段:工号 姓名 部门
公司有3个部门,但是有1个亿的员工,那意味着部门这个字段需要重复存储,部门名字越长,越浪费
解决方法:
我们完全可以定义一个部门表
然后让员工信息表关联该表,如何关联,即foreign key
create table dep( id int primary key auto_increment, name varchar(20), comment varchar(50) );
create table emp( id int primary key auto_increment, name varchar(16), age int, dep_id int, foreign key(dep_id) references dep(id) on update cascade on delete cascade );
insert dep(name,comment) values ("IT","搞技术"), ("sale","卖东西"), ("HR","招聘") ; insert emp(name,age,dep_id) values ("egon",18,1), ("tom",19,2), ("lili",28,2), ("jack",38,1), ("lxx",78,3);
update dep set id=33 where name ="HR";
delete from dep where id=2; # 删除dep表中的id为2的销售部门,emp表中对应dep销售部门的员工也跟着删除了 mysql> delete from dep where id=2; Query OK, 1 row affected (0.23 sec) mysql> select * from dep; +----+------+-----------+ | id | name | comment | +----+------+-----------+ | 1 | IT | 搞技术 | | 33 | HR | 招聘 | +----+------+-----------+ 2 rows in set (0.00 sec) mysql> select * from emp; +----+------+------+--------+ | id | name | age | dep_id | +----+------+------+--------+ | 1 | egon | 18 | 1 | | 4 | jack | 38 | 1 | | 5 | lxx | 78 | 33 | +----+------+------+--------+ 3 rows in set (0.00 sec)
egon 九阳神功 egon 祥龙十八掌 egon 易筋经 egon 九阴真经 egon 葵花宝典 jason 九阳神功 jason 祥龙十八掌 lxx 易筋经 lxx 九阴真经 hxx 祥龙十八掌 hxx 易筋经 hxx 九阴真经 # 多个作者编写一本书 # 一个作者编写多本书 create table author( id int primary key auto_increment, name varchar(16) ); create table book( id int primary key auto_increment, name varchar(20) ); create author2book( id int primary key auto_increment, author_id int, book_id int, foreign key(author_id) references author(id) on update cascade on delete cascade, foreign key(book_id) references book(id) on update cascade on delete cascade );
#一定是student来foreign key表customer,这样就保证了: #1 学生一定是一个客户, #2 客户不一定是学生,但有可能成为一个学生 create table customer( id int primary key auto_increment, name varchar(20) not null, qq varchar(10) not null, phone char(16) not null ); create table student( id int primary key auto_increment, class_name varchar(20) not null, customer_id int unique, # 该字段一定要是唯一的 foreign key(customer_id) references customer(id) # 外键的字段一定要保证unique on delete cascade on update cascade ); # 增加客户 insert into customer(name,qq,phone) values ('蔡子奇','31811231',13811341220), ('孙宗伟','123123123',15213146809), ('胡玉康','283818181',1867141331), ('刘洋','283818181',1851143312), ('杨逸轩','888818181',1861243314), ('杨杰','112312312',18811431230) ; # 增加学生 insert into student(class_name,customer_id) values ('牛逼1班',3), ('装逼2班',4), ('装逼2班',5) ;
>>分析步骤: 1、先站在左表的角度去找 是否左表的多条记录可以对应右表的一条记录,如果是,则证明左表的一个 字段foreign key 右表一个字段(通常是id) 2、再站在右表的角度去找 是否右表的多条记录可以对应左表的一条记录,如果是,则证明右表的一个 字段foreign key 左表一个字段(通常是id) 3、总结: # 多对一: 如果只有步骤1成立,则是左表多对一右表 如果只有步骤2成立,则是右表多对一左表 # 多对多 如果步骤1和2同时成立,则证明这两张表时一个双向的多对一,即多对多, 需要定义一个这两张表的关系表来专门存放二者的关系 # 一对一: 如果1和2都不成立,而是左表的一条记录唯一对应右表的一条记录,反之亦然。这种情况 很简单,就是在左表foreign key右表的基础上,将左表的外键字段设置成unique即可
# 一对多或称为多对一 三张表:出版社,作者信息,书 一对多(或多对一):一个出版社可以出版多本书 关联方式:foreign key # 多对多 三张表:出版社,作者信息,书 多对多:一个作者可以写多本书,一本书也可以有多个作者,双向的一对多,即多对多 关联方式:foreign key+一张新的表 # 一对一 两张表:学生表和客户表 一对一:一个学生是一个客户,一个客户有可能变成一个学校,即一对一的关系 关联方式:foreign key+unique