约束条件(补充)

约束条件(补充)

概要

  • 约束条件之主键

  • 约束条件之自增

  • 约束条件之外键


详情

  • 约束条件之主键

主键:primary key
1.从约束条件层面来说,主键相当于
    not null unigue(非空且唯一)
        create table t1(id int primary key);
        create table t2(id int not null unique);
    # 可知,t1表的id字段与t2表一样也具有非空且唯一的性质
    
2.主键是InnoDB存储引擎组织数据表的依据
    (1) InnoDB规定一个表必须'有且只有'一个主键
    (2) 如果未指定主键,则会自动采用隐藏字段作为主键
    (3) 如果表中没有主键但存在'非空且唯一'的字段,则自上而下的第一个该类字段会自动变成该表的主键
    (4) 主键具有索引的功能可以加快查询速度,如果是隐藏字段则无法加快查询速度,故不推荐使用此方式
    eg:
        create table test_PK(
            id int,
            name char(16)
            age int not null unique,
            phone char(11) not null unique
        );
在SQL语句中,除了可以将单列设为主键以外,也可以将多列的组合设为主键
eg:
    create table test_mul_PK(
        id int,
        name char(4),
        primary key(id,name)
    );


  • 约束条件之自增

假设有这样一张表
create table test_ai(
    id int primary key,
    name varchar(16)
);
如果表中已存在特别多的数据,若主键是手动增加再插入的序号,可能会令使用者难以知晓已存在的主键值,这时方便起见需要用到SQL语句的自增语句,配合主键一起使用
create table test_auto_increment(
    id int primary key auto_increment,
    name varchar(16)
);
# 主键自增的表插入数据时无需对主键赋值
insert into test_auto_increment(name) values('Leoric');
insert into test_auto_increment(name) values('Leo');
# 创建表时,一般将id类字段作为主键,写为
    id int primary key auto_increment

1.delete操作删除数据时不会重置或回退当前自增主键的值
eg: delete from test_auto_increment where id=2;
2.truncate操作清空数据时可以同时清空当前自增主键的值
eg: truncate test_auto_increment;

 

 

 


  • 约束条件之外键

外键的由来

# 引入  如果存在这样一张员工表
| 编号 | 姓名 | 年龄 | 部门名 | 部门描述 |
这张表在使用上存在以下几点问题
    1.表结构不清晰
        这是张员工表还是部门表?
    2.表数据重复
        会有多个员工在同一个部门,部门信息重复?
    3.数据扩展性很差
        如果要修改部门名,需要修改的数据量?
# 如果要缓解上述问题,需要将表拆开
    1.员工表: 员工编号 员工姓名 年龄
    2.部门表: 部门编号 部门名称 部门描述
# 这样两张表将毫无关联    
"""
    解决方案:可以在员工表中添加一个部门编号字段(外键)
"""

表关系的种类

外键:记录表与表之间数据关系的字段。

表与表之间数据关系分为四种:
    一对多、多对多、一对一、无关系。
'''判断表关系遵循换位思考原则'''
1、一对多关系
# 判断表关系,以员工表和部门表为例
1.先站在员工表的层面
    问:一个员工能否对应多个部门?
    答:不可以
2.再站在部门表的层面
    问:一个部门能否对应多个员工?
    答:可以
3.由此可见
    一方可以,另一方不可以,员工表与部门表的关系即为"一对多"
"一对多"的表关系中,外键字段创建在''的那一方
eg:员工表与部门表
create table emp(
    id int primary key auto_increment,
    name char(16),
    age int,
    dep_id int,
    foreign key(dep_id) references dep(id)
);
create table dep(
    id int primary key auto_increment,
    dep_name char(16),
    dep_desc char(32)
);

外键的特性
# 创建表时先写基本字段类型与约束条件,然后在考虑外键关系
1.创建表时必须先创建被关联表(自身不存在外键字段的表,故上述先创建员工表会报错)
2.插入记录时必须先插入被关联表的记录,再插入关联表的记录
3.被关联表中的记录无法自由删除和修改
4.如果要实现被关联表和关联表外键字段的自由删除和修改,则需使用级联更新/级联删除功能
eg:
    create table emp_cas(
        id int primary key auto_increment,
        name char(16),
        age int,
        dep_id int,
        foreign key(dep_id) references dep(id)
        on update cascade   # 级联更新
        on delete cascade   # 级联删除
    );
往上一节创建的dep部门表中插入记录
insert into dep(dep_name,dep_desc) values('技术部','高精尖技术持有者');
insert into dep(dep_name,dep_desc) values('财务部','金融管理者');
往emp_cas级联员工表中插入记录
insert into emp_cas(name,age,dep_id) values('Leoric',18,'1'),('Jack',20,'2');

修改被关联表的主键
update dep set id=200 where id=2;

删除被关联的表的记录
delete from dep where id=222; 

2、多对多关系
# 判断表关系,以书籍表和作者表为例
1.先站在书籍表层面
    问:一本书籍能否对应多个作者?
    答:可以
2.再站在作者表层面
    问:一个作者能否对应多本书籍?
    答:可以
3.由此可见
    两方均可以,书籍表和作者表的关系即为"多对多"
eg:书籍表与作者表
create table book(
    id int primary key auto_increment,
    name char(16),
    price int,
    author_id int,
    foreign key(author_id) references author(id)
    on update cascade
    on delete cascade
);
create table author(
    id int primary key auto_increment,
    name char(16),
    age int,
    book_id int,
    foreign key(book_id) references book(id)
    on update cascade
    on delete cascade
);

'''
    这是错误操作!!!!!!
    由于两表互为外键关系,先创建任意一张都会报错
    故多对多表关系中,外键字段需创建在第三张关系表中
'''
create table book(
    id int primary key auto_increment,
    name char(16),
    price int
);
create table author(
    id int primary key auto_increment,
    name char(16),
    age int
);
create table book_from_author(
    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
);
3、一对一关系
# 判断表关系,以用户表与用户详情表为例
1.先站在用户表层面
    问:一个用户能否对应多个详情?
    答:不可
2.再站在用户详情表层面
    问:一个用户详情能否对应多个用户?
    答:不可
3.由此可见
    两方都不可以,表关系可能是"一对一"也可能没有关系
    这里用户与用户详情显然是"一对一"关系
外键可以创建在任意一张表,最好创建在查询频率高的表中,这里由于一般通过用户去查询用户的详情,故建在用户表比较合适
create table user(
    id int primary key auto_increment,
    name varchar(16),
    detail_id int unique,
    foreign key(detail_id) references user_detail(id)
    on update cascade
    on delete cascade
);
create table user_detail(
    id int primary key auto_increment,
    phone bigint,
    addr varchar(16)
);
# 和一对多的表关系的区别在于外键具有唯一约束
4、表关系总结
判断思路:
1.先从表1看
    问:表1的一条记录能否对应表2的多条记录?
    答:可以/不可以
2.再从表2
    问:表2的一条记录能否对应表1的多条记录?
    答:可以/不可以
# 结论
  若双方均为可以,则表关系为多对多。
  若双方均为不可以,则表关系为一对一或者没有关系。
  若一方可以,另一方不可以,则表关系为一对多。

修改表相关SQL语句

1.修改表名  
    alter table 旧表名 rename 新表名;

2.增加字段
    alter table 表名 add 字段名 数据类型[完整性约束],add 字段名 数据类型[完整性约束]; # 增加多个字段
    alter table 表名 add 字段名 数据类型[完整性约束] first; #在首位增加字段(很少用)
    alter table 表名 add 字段名 数据类型[完整性约束] after 字段名; # 在某字段后增加字段

3.删除字段
    alter table 表名 drop 字段名;

 

4.修改字段
alter table 表名 modify 字段名 数据类型 [完整性约束];
alter table 表名 change 旧字段名 新字段名 旧数据类型 [完整性约束]
alter table 表名 change 旧字段名 新字段名 新数据类型 [完整性约束]

modify关键字只能修改字段数据类型和完整性约束条件,不能修改字段名。
change关键字能修改字段名、字段数据类型和完整性约束条件。

作业

书籍表与出版社表
1.先从书籍表层面看
问:一本书籍能否在多家出版社出版?
答:不可以
2.再从出版社表层面看
问:一家出版社能否出多本书籍
答:可以
3.由此可见,书籍表与出版社表是"一对多"的关系,外键要设在多的一方,即书籍表
create table publisher(
    id int primary key auto_increment,
    name varchar(16)
);
create table books(
    id int primary key auto_increment,
    name varchar(16),
    pub_id int,
    foreign key(pub_id) references publisher(id)
    on update cascade
    on delete cascade
);
insert into publisher(name) values('人民出版社');
insert into publisher(name) values('人民邮电出版社');
insert into books(name,pub_id) values('gxdxy',1);
insert into books(name,pub_id) values('理想国',1);
insert into books(name,pub_id) values('Python编程 从入门到实践',2);

老师表与课程表
1.先从老师表层面看
问:一名老师能否教多个课程?
答:不可以
2.再从课程表层面看
问:一个课程能否被多个老师教?
答:不可以
3.由此可见,老师表与课程表是"一对一"的关系,外键建在课程表
create table teachers(
    id int primary key auto_increment,
    name varchar(16)
);
create table lessons(
    id int primary key auto_increment,
    name varchar(16),
    teach_id int unique,
    foreign key(teach_id) references teachers(id)
    on update cascade
    on delete cascade
);
insert into teachers(name) values('无极剑圣');
insert into teachers(name) values('疾风剑豪');
insert into lessons(name,teach_id) values('阿尔法突袭',1);
insert into lessons(name,teach_id) values('狂风绝息斩',2);

学生表与班级表
1.先从学生表层面看
问:一名学生能否有多个班级?
答:不可以
2.再从班级表层面看
问:一个班级能否有多个学生?
答:可以
3.由此可见,学生表与班级表是"一对多"的关系,外键建在学生表
create table classes(
    id int primary key auto_increment,
    name varchar(16)
);
create table students(
    id int primary key auto_increment,
    name varchar(16),
    cla_id int,
    foreign key(cla_id) references classes(id)
    on update cascade
    on delete cascade
);
insert into classes(name) values('高三3班');
insert into classes(name) values('高三4班');
insert into students(name,cla_id) values('Seven',1);
insert into students(name,cla_id) values('Ace',2);
insert into students(name,cla_id) values('Leo',2);
insert into students(name,cla_id) values('Jack',2);

书籍表与作者表
1.先从书籍表层面看
问:一本书籍能否由多个作者创作?
答:不可以
2.再从作者表层面看
问:一个作者能否创作多本书籍?
答:可以
3.由此可见,书籍表与作者表是"一对多"的关系,外键要设在多的一方,即书籍表
create table authors(
    id int primary key auto_increment,
    name varchar(16)
);
create table books2(
    id int primary key auto_increment,
    name varchar(16),
    auth_id int,
    foreign key(auth_id) references authors(id)
    on update cascade
    on delete cascade
);
insert into authors(name) values('东野圭吾');
insert into authors(name) values('阿加莎-克里斯蒂');
insert into books2(name,auth_id) values('白夜行',1);
insert into books2(name,auth_id) values('解忧杂货店',1);
insert into books2(name,auth_id) values('鸽群中的猫',2);

作者表与作者详情表
1.先从作者表层面看
问:一名作者能否对应多个详情?
答:不可以
2.再从作者详情表层面看
问:一个作者详情能否对应多名作者?
答:不可以
3.由此可见,作者表与作者详情表是"一对一"的关系,外键要设在查询频率高的一方,即作者表
create table authors2(
    id int primary key auto_increment,
    name varchar(16),
    info_id int,
    foreign key(info_id) references authors_info(id)
    on update cascade
    on delete cascade
);
create table authors_info(
    id int primary key auto_increment,
    phone char(11),
    addr varchar(16)
);
insert into authors_info(phone,addr) values('66666666666','上海市嘉定区');
insert into authors_info(phone,addr) values('88888888888','上海市宝山区');
insert into authors2(name,info_id) values('Leo',1);
insert into authors2(name,info_id) values('Ace',2);

 

 

 

posted @ 2021-09-06 22:52  Leguan001  阅读(127)  评论(0)    收藏  举报