MySQL约束条件与表对应关系

197 阅读6分钟

约束条件之主键

primary key  主键
# 主键就相当于是新华字典的目录,可以加快查询速度
1.单从约束条件而言,主键等价于非空且唯一(not null unique)
    create table t1(
        id int not null unique,  # 相当于 id int primary key,
        name varchar(32)
    );
2.InnoDB存储引擎规定一张表必须有且只有一个主键字段
	2.1 如果创建的表中没有主键也没有非空且唯一的字段,那么InnoDB存储引擎会自动采用一个隐藏的字段作为主键。
	2.2 如果创建的表中没有主键,但是有非空且唯一的字段,那么InnoDB存储引擎会自动将该字段升级为主键,如果有多个这种类型的字段,则只会升级第一个。
	create table t2(
            pid int not null unique,  # 升级为主键
            wid int not null unique,
            nid int not null unique,
            name varchar(32)
        );
    
mysql> desc t2;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| pid   | int(11)     | NO   | PRI | NULL    |       |
| wid   | int(11)     | NO   | UNI | NULL    |       |
| nid   | int(11)     | NO   | UNI | NULL    |       |
| name  | varchar(32) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
# 第一个非空且唯一的字段 pid 被升级为了主键

3.创建表的时候都应该有一个'id'字段 并且这个字段一般应该被设置为主键
    uid pid wid id 等等...
单列主键:
    id int primary key 
联合主键: # 用的很少
    sid int,
    nid int,
    primary key (sid, nid)     

约束条件之自增

auto_increment
该约束条件不能单独使用,必须跟在键后面(一般是跟在主键或外键后面)
    create table t3(
        id int primary key auto_increment,
        name varchar(32)
    );
insert into t3(name) values('jason');
insert into t3(name) values('jack');
select * from t3;
    +----+-------+
    | id | name  |
    +----+-------+
    |  1 | jason |
    |  2 | jack  |
    +----+-------+
# 即使没有往id字段添加值,由于auto_increment的存在,我们在insert的时候会自动往表的id字段中添加1、2、3...的编号。 
自增的特点:
    自增的操作不会因为执行删除数据的操作而回退或者重置
        DELETE from t3 where id = 2;  # 删除id为2的记录
        insert into t3(name) values('kevin')  # 新增记录
        select * from t3;
        +----+-------+
        | id | name  |
        +----+-------+
        |  1 | jason |
        |  3 | kevin |
        +----+-------+
# 新增数据的id不会从2开始 而是从3开始
如果非要重置自增的主键 需要格式化表(删除表中所有数据)
truncate 表名;  # 删除表数据并重置主键自增

约束条件之外键

1.什么是外键
    如果一个表的某个字段指向另一个表的主键,这个字段就称为外键。被指向的表称为主表或父表,负责指向的表称为从表或子表。
2.外键的作用
    · 为了一张表的数据不要太过冗余
    · 保持数据的一致性,完整性。
3.外键字段的作用
    专门用来记录表与表之间数据的关系
4.外键的创建
语法:foreign key(外键字段) references 主表(被关联字段)

'建表时先写普通字段,之后在写外键字段'
    create table dep(  # 先创主表:部门表
        id int primary key auto_increment,
        dep_name varchar(32),
        dep_desc varchar(32)
    );
    create table emp(  # 再创从表:员工表
        id int primary key auto_increment,
        name varchar(32),
        gender enum('male', 'female') default 'male',
        dep_id int,  # 外键字段  链接dep表中的id字段
        foreign key(dep_id) references dep(id)        	
    );
"
1.创建表的时候要先创建被关联的表(没有外键),再创建关联的表(有外键)
2.插入数据的时候,针对外键字段只能填写被关联表字段已经出现过得数据值
3.被关联字段无法直接修改和删除(需要设置级联更新/级联删除)
"
5.级联更新/级联删除
定义;被关联的的数据一旦变动,关联的数据也要跟着变动。
# 部门表
create table dep1(
	id int primary key auto_increment,
	dep_name varchar(32),
	dep_desc varchar(32)    
);
# 员工表
create table emp1(
    id int primary key auto_increment,
    name varchar(32),
    gender enum('male','female') default 'male',
    dep1_id int,  # 外键
    foreign key(dep1_id) references dep1(id)  # 建立关系
    on update cascade  # 级联更新
    on delete cascade  # 级联删除
);
扩展:
    在实际工作中很多时候可能并不需要使用外键,因为外键增加了表与表之间的耦合度,不便于操作,资源消耗增加。
    我们如果想描述出表数据间的关系又不想使用外键,可以多写几条SQL语句。

表关系之一对多

'没有多对一  只有一对多'
以员工表和部门表为例
    一个员工只能存在于一个部门,一个部门内有多个员工。
    部门表和员工表之间是一对多关系,部门是1,员工是多。
多对多关系的表建立外键:
    对于一对多关系,我们只需要在'多'的这张表中建立'一'的外键关联即可,而'一'这边的表不需要做任何修改。
    比如员工和部门表:部门表不变,员工表增加部门id作为外键关联部门表。		

mysql> desc emp1;
+---------+-----------------------+------+-----+---------+----------------+
| Field   | Type                  | Null | Key | Default | Extra          |
+---------+-----------------------+------+-----+---------+----------------+
| id      | int(11)               | NO   | PRI | NULL    | auto_increment |
| name    | varchar(32)           | YES  |     | NULL    |                |
| gender  | enum('male','female') | YES  |     | male    |                |
| dep1_id | int(11)               | YES  | MUL | NULL    |                |
+---------+-----------------------+------+-----+---------+----------------+

表关系之多对多

以书籍表和作者表为例:
    一本书籍可以由多个作者共同完成
    一个作者可以编写多本书籍  
针对多对多关系,外键字段不能建立在任意一方!必须单独开设第三张表,专门存储数据关系。
create table book(
    id int primary key auto_increment,
    tittle varchar(32)    
);
create table auther(
    id int primary key auto_increment,
    name varchar(32)    
);
# 第三张表 专门记录book表和auther表的关系
create table book_auther(
    id int primary key auto_increment,
    book_id int,  # 外键1 关联book表
    auther_id int,  # 外键2 关联auther表
    foreign key(book_id) references book(id)
    on update cascade on delete cascade,
    foreign key(auther_id) references autger(id)
    on update cascade on delete cascade    
);
+-----------+---------+------+-----+---------+----------------+
| Field     | Type    | Null | Key | Default | Extra          |
+-----------+---------+------+-----+---------+----------------+
| id        | int(11) | NO   | PRI | NULL    | auto_increment |
| book_id   | int(11) | YES  | MUL | NULL    |                |
| auther_id | int(11) | YES  | MUL | NULL    |                |
+-----------+---------+------+-----+---------+----------------+

表关系之一对一

以用户表和用户详情表为例
    一个用户只有唯一的一份用户信息
    一份用户信息只能属于一个用户
针对一对一的表关系,外键字段设置在任何一张表都可以,但是建议设置在查询频率较高的表中,以便后续查询。
create table userdetail(
    id int primary key auto_increment,
    phone char(11)
);
create table user(
    id int primary key auto_increment,
    name varchar(32),
    detail_id int unique,
    foreign key(detail_id) references userDetail(id)
    on update cascade on delete cascade    
);

mysql> desc user;
+-----------+-------------+------+-----+---------+----------------+
| Field     | Type        | Null | Key | Default | Extra          |
+-----------+-------------+------+-----+---------+----------------+
| id        | int(11)     | NO   | PRI | NULL    | auto_increment |
| name      | varchar(32) | YES  |     | NULL    |                |
| detail_id | int(11)     | YES  | UNI | NULL    |                |
+-----------+-------------+------+-----+---------+----------------+

练习

判断下列表数据关系 并自定义创建出表
	ps:有些表数据关系不是确定 根据具体业务可能有变化
1.服务器表与应用程序表  
	一对多?多对多?
2.课程表与班级表  
	多对多
	create table class(
            id int primary key auto_increment,
            name varchar(32) not null,
            stu_num int not NULL
        );
        create table course(
            id int primary key auto_increment,
            name varchar(32) not null
        );
        create table class_course(
            class_id int ,
            course_id int,
            foreign key(class_id) references class(id)
            on update CASCADE on delete cascade,
            foreign key (course_id) references course(id)
            on update cascade on delete CASCADE
        );
        desc CLass;
        desc course;
        desc class_course;

        insert into course(name) values('java');
        insert into class (name,stu_num) values('三年二班',30);

        select * from class;
        select * from course;
3.学生表与班级表
	一对多
	create table stu(
            id int PRIMARY key auto_increment,
            name varchar(32) not null,
            gender enum('male','female') DEFAULT 'male',
            hobby set('唱','跳','rap','篮球'),
            class_id int , # 外键
            foreign key (class_id) REFERENCES class(id)
            on update cascade on delete cascade
        );
        desc stu;
        insert into stu(name, hobby, class_id)
        values('张三','唱,跳,rap',1);
        select * from stu;
4.老师表与课程表
	一对一
        create table teacher(
            id int primary key auto_increment,
            name varchar(32) not null,
            age int ,
            course_id int ,
            foreign key (course_id) references course(id)
            on update cascade on delete CASCADE
        );
        desc teacher;
        insert into teacher(name,course_id)
        values ('jason',1);
        select * from teacher;
5.书籍表与出版社表
	一对多
    create table press(
        id int primary key auto_increment,
        name varchar(32)
    );

    create table book(
        id int primary key auto_increment,
        name varchar(32),
        press_id int ,
        foreign key(press_id) references press(id)
        on update cascade on delete CASCADE
    );
    desc press;
    desc book;