【3.0】数据库知识点小结数据库升级

【3.0】数据库知识点小结数据库升级

【一】约束条件

【1】default(默认值)

(1)补充

在插入数据的时候可以指定字段

  • 创建数据库
create database day02;

# Database changed
  • 创建表
create table t1(
	id int,
    name char(16)
);

# Query OK, 0 rows affected (0.77 sec)
  • 插入数据
insert into t1(name,id) values(
	"dream",18
);

# Query OK, 1 row affected (0.31 sec)

可以根据指定字段进行插入数据,如果不写则默认按位置进行插入数据

  • 查看数据
select * from t1;
+------+-------+
| id   | name  |
+------+-------+
|   18 | dream |
+------+-------+
1 row in set (0.00 sec)

(2)设置默认值

  • 创建表
create table t2(
	id int,
    name char(16) not null,
    gender enum('male','female','others') default 'male'
);

# Query OK, 0 rows affected (0.61 sec)
  • 查看表
desc t2;
+--------+--------------------------------+------+-----+---------+-------+
| Field  | Type                           | Null | Key | Default | Extra |
+--------+--------------------------------+------+-----+---------+-------+
| id     | int(11)                        | YES  |     | NULL    |       |
| name   | char(16)                       | NO   |     | NULL    |       |
| gender | enum('male','female','others') | YES  |     | male    |       |
+--------+--------------------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
  • 插入数据1
insert into t2 (id,name) values(1,"dream");

# Query OK, 1 row affected (0.21 sec)
  • 插入数据2
insert into t2 (id,name,gender) values(2,"mengmeng",'female');

# Query OK, 1 row affected (0.21 sec)
  • 查看数据
select * from t2;
+------+----------+--------+
| id   | name     | gender |
+------+----------+--------+
|    1 | dream    | male   |
|    2 | mengmeng | female |
+------+----------+--------+
2 rows in set (0.00 sec)

第一条数据没有插入gender,使用默认的gender

第二条使用了自己插入的数据

【2】unique(唯一)

(1)单列唯一

  • 创建表
create table t3(
	id int unique,
    name char(16)
);

# Query OK, 0 rows affected (0.74 sec)
  • 查看表
desc t3;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| id    | int(11)  | YES  | UNI | NULL    |       |
| name  | char(16) | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
2 rows in set (0.00 sec)
  • 插入多条数据
insert into t3 values(1,"dream")(1,"mengmeng");

# ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(1,"mengmeng")' at line 1
  • 插入数据2
insert into t3 values(1,"dream")(2,"zuimeng");

# Query OK, 1 row affected (0.17 sec)
  • 查看数据
select * from t3;
+------+---------+
| id   | name    |
+------+---------+
|    2 | zuimeng |
|    1 | dream   |
+------+---------+
2 rows in set (0.00 sec)

插入数据正常

(2)联合唯一

比如我们的IP和端口

​ 单个可以重复,联合到一起不能重复

  • 创建表
create table t4(
	id int,
    ip char(16),
    port int,
    unique(ip,port)
);

# Query OK, 0 rows affected (0.97 sec)
  • 插入数据
insert into t4 values(1,'127.0.0.1',8080);
# Query OK, 1 row affected (0.20 sec)

insert into t4 values(2,'127.0.0.1',8081);
# Query OK, 1 row affected (0.20 sec)

insert into t4 values(3,'127.0.0.2',8080);
# Query OK, 1 row affected (0.20 sec)

insert into t4 values(4,'127.0.0.1',8080);
# ERROR 1062 (23000): Duplicate entry '127.0.0.1-8080' for key 'ip'
  • 查看数据
select * from t4;
+------+-----------+------+
| id   | ip        | port |
+------+-----------+------+
|    1 | 127.0.0.1 | 8080 |
|    2 | 127.0.0.1 | 8081 |
|    3 | 127.0.0.2 | 8080 |
+------+-----------+------+
3 rows in set (0.00 sec)

【3】primary key(主键)

(1)约束条件效果:非空且唯一

单从约束条件效果上看

​ primary key = not null + unique

​ 非空且唯一

  • 创建表
create table t5(
	id int primary key
);

# Query OK, 0 rows affected (0.87 sec)
  • 查看表
desc t5;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | NO   | PRI | NULL    |       |
+-------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)
  • 插入数据
insert into t5 values(null);
# ERROR 1048 (23000): Column 'id' cannot be null

insert into t5 values(1);
# Query OK, 1 row affected (0.17 sec)

insert into t5 values(1);
# ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

(2)是Innodb引擎组织数据的依据

它除了有约束效果外,还是Innodb存储引擎组织数据的依据

Innodb存储在创建表的时候肯定有 primary key

​ 因为他类似于书的目录,能够帮助提示查询效率并且也是建表的依据

(1) 一张表中有且只有一个主键,如果没有设置主键,那么会从上往下搜索直到遇到一个非空且唯一的字段,将它自动升级为主键

  • 创建表
create table t6(
	id int,
    name char(16),
    age int not null unique,
    addr char(32) not null unique
);

# Query OK, 0 rows affected (0.86 sec)
  • 查看表
desc t6;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| id    | int(11)  | YES  |     | NULL    |       |
| name  | char(16) | YES  |     | NULL    |       |
| age   | int(11)  | NO   | PRI | NULL    |       |
| addr  | char(32) | NO   | UNI | NULL    |       |
+-------+----------+------+-----+---------+-------+
4 rows in set (0.00 sec)

age 字段自动提升为 primary key 字段

(2) 如果表中没有主键,也没有其他任何非空且唯一字段,那么Innodb会采用自己内部提供的一个隐藏字段作为主键。隐藏意味着无法使用,且无法提升查询速度。

(3) 一张表中都应该具有一个主键字段,并且通常将 id/uid/sid 字段作为主键。

单个字段主键

create table t7(
	id int primary key,
    name char(36)
);

联合主键(多个字段联合起来作为表的主键,本质还是一个主键)

create table t7(
	id int ,
    ip char(16),
    port int,
    primary key(ip,port)
);

# Query OK, 0 rows affected (0.83 sec)
desc t7;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| id    | int(11)  | YES  |     | NULL    |       |
| ip    | char(16) | NO   | PRI | NULL    |       |
| port  | int(11)  | NO   | PRI | NULL    |       |
+-------+----------+------+-----+---------+-------+
3 rows in set (0.00 sec)

总结:id字段在创建时,一定要加 主键

【4】auto_increment(自增)

在创建数据时,会自动增加

  • 创建表
create table t8(
	id int primary key auto_increment,
    name char(16)
);

# Query OK, 0 rows affected (0.96 sec)
  • 查看表
desc t8;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| id    | int(11)  | NO   | PRI | NULL    | auto_increment |
| name  | char(16) | YES  |     | NULL    |                |
+-------+----------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
  • 插入数据
insert into t8(name) values("dream"),("hope"),("meng");

# Query OK, 3 rows affected (0.18 sec)
# Records: 3  Duplicates: 0  Warnings: 0
  • 查看数据
select * from t8;
+----+-------+
| id | name  |
+----+-------+
|  1 | dream |
|  2 | hope  |
|  3 | meng  |
+----+-------+
3 rows in set (0.00 sec)

auto_increment:只能加载 key 键上 ,不能在普通字段上使用

通常是加在主键上

【5】结论

(1)主键的标准语法

  • 在创建表的唯一标识(id/sid/uid)时的标准语法
create table t1(
	id int primary key auto_increment
);

(2)主键自增

  • 在使用以下命令在删除表的时候,已经自增过的主键不会被删除
    • 新创建的数据会延续上一次删除之前主键自增的位置进行自增
delete from 表名;
  • 可以使用以下命令删除表,达到删除主键的目的
    • 清空表数据并且重置表的主键
truncate 表名;

【二】外键

【1】表与表之间建立关系

  • 表与表之间只有三种关系
    • 一对一
    • 多对弈
    • 一对多
  • 在MySQL的关系中没有多对一的说法
  • 一对多 多对多 都叫 一对多

(1)定义一张表

id name gender dep_name dep_desc
  • 该表的组织结构不清晰
  • 浪费硬盘空间
  • 数据的扩展性极差,修改起来的难度极差

(2)如何优化?

  • 将员工表拆分建立联系

    • 拆成员工表 + 部门表
    • 建立联系
  • 员工表

id dep_name dep_desc
  • 部门表
id name gender dep_id

【2】什么是外键(Foreign Key)

外键(Foreign Key)是关系数据库中的一个概念,用于建立两个关系表之间的关联关系。

它是一个列或一组列,用来指向另一个表的主键。

外键在建立数据表与数据表之间的关系时起到了重要的作用。

【3】一对多关系

(1)一对多关系,外键建在字段多的地方

(2)在创建表的时候一定要先创建被关联表

(3)在录入数据的时候必须先录入被关联表

在确定表与表关系之前,首先要换位思考

例如

  • 在员工表
    • 要考虑到员工表里面的一个员工是否能对应部门表里面的多个部门
  • 在部门表
    • 要考虑到一个部门能否对应员工表里面的多个员工
  • 总结
    • 员工表与部门表只是单向的一对多成立,那么员工表与部门表就是一对多的表关系
  • 创建部门表
create table dep(
	id int primary key auto_increment,
    dep_name char(16),
    dep_desc char(32)
);

#Query OK, 0 rows affected (0.82 sec)
  • 查看表(部门表)
desc dep;
+----------+----------+------+-----+---------+----------------+
| Field    | Type     | Null | Key | Default | Extra          |
+----------+----------+------+-----+---------+----------------+
| id       | int(11)  | NO   | PRI | NULL    | auto_increment |
| dep_name | char(16) | YES  |     | NULL    |                |
| dep_desc | char(32) | YES  |     | NULL    |                |
+----------+----------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
  • 创建员工表(员工表)
create table emp(
	id int primary key auto_increment,
    emp_name char(16),
    emp_gender enum("male","female","others") default "male",
    dep_id int,
	foreign key (dep_id) references dep(id)
);

# Query OK, 0 rows affected (0.92 sec)
  • 查看表(员工表)
desc emp;
+------------+--------------------------------+------+-----+---------+----------------+
| Field      | Type                           | Null | Key | Default | Extra          |
+------------+--------------------------------+------+-----+---------+----------------+
| id         | int(11)                        | NO   | PRI | NULL    | auto_increment |
| emp_name   | char(16)                       | YES  |     | NULL    |                |
| emp_gender | enum('male','female','others') | YES  |     | male    |                |
| dep_id     | int(11)                        | YES  | MUL | NULL    |                |
+------------+--------------------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
  • 插入数据(部门表)
insert into dep(dep_name,dep_desc) values("sm运动社","日常活动"),("游戏社","休闲娱乐"),("技术部","能力提升"),("cp外交部","社交沟通");

# Query OK, 4 rows affected (0.14 sec)
# Records: 4  Duplicates: 0  Warnings: 0
  • 插入数据(员工表)
insert  into emp(emp_name,emp_gender,dep_id) values("dream","male",1),("chimeng","female",4),("mengmeng","female",2),("drunkmeng","male",3);

# Query OK, 4 rows affected (0.13 sec)
# Records: 4  Duplicates: 0  Warnings: 0
  • 查看数据(部门表)
select * from dep;
+----+-------------+--------------+
| id | dep_name    | dep_desc     |
+----+-------------+--------------+
|  1 | sm运动社    | 日常活动     |
|  2 | 游戏社      | 休闲娱乐     |
|  3 | 技术部      | 能力提升     |
|  4 | cp外交部    | 社交沟通     |
+----+-------------+--------------+
4 rows in set (0.00 sec)
  • 查看数据(员工表)
select * from emp;
+----+-----------+------------+--------+
| id | emp_name  | emp_gender | dep_id |
+----+-----------+------------+--------+
|  1 | dream     | male       |      1 |
|  2 | chimeng   | female     |      4 |
|  3 | mengmeng  | female     |      2 |
|  4 | drunkmeng | male       |      3 |
+----+-----------+------------+--------+
4 rows in set (0.00 sec)

(1)正常命令修改被关联表中的某个字段

  • 修改 emp 表中的 dep_id 字段或者 dep 表里面的 id 字段

  • 修改/删除命令

# 修改某张表中的关联值
update dep set id = 200 where id =2;

#ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`day02`.`emp`, CONSTRAINT `emp_ibfk_1` FOREIGN KEY (`dep_id`) REFERENCES `dep` (`id`))

# 删除表命令
delete from dep;
# ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`day02`.`emp`, CONSTRAINT `emp_ibfk_1` FOREIGN KEY (`dep_id`) REFERENCES `dep` (`id`))

无法通过正常修改命令对其进行修改

(2)解决办法

  • (1) 先删除教学部对应的员工数据 ,之后再删除部门
  • (2) 真正做到数据之间有关系
    • 更新就同步更新
    • 删除就同步删除

级联更新

级联删除

create table emp(
	id int primary key auto_increment,
    emp_name char(16),
    emp_gender enum("male","female","others") default "male",
    dep_id int,
	foreign key (dep_id) references dep(id) 
    on uodate cascade 
    on delete cascade
);

# Query OK, 0 rows affected (0.92 sec)
  • 删除表
drop table emp;
# Query OK, 0 rows affected (0.53 sec)

drop table dep;
Query OK, 0 rows affected (0.25 sec)
  • 创建表
create table emp(
	id int primary key auto_increment,
    emp_name char(16),
    emp_gender enum("male","female","others") default "male",
    dep_id int,
	foreign key (dep_id) references dep(id) 
    on update cascade 
    on delete cascade
);

# Query OK, 0 rows affected (0.92 sec)
create table dep(
	id int primary key auto_increment,
    dep_name char(16),
    dep_desc char(32)
);

#Query OK, 0 rows affected (0.82 sec)
  • 插入数据
insert into dep(dep_name,dep_desc) values("sm运动社","日常活动"),("游戏社","休闲娱乐"),("技术部","能力提升"),("cp外交部","社交沟通");

# Query OK, 4 rows affected (0.14 sec)
# Records: 4  Duplicates: 0  Warnings: 0
insert  into emp(emp_name,emp_gender,dep_id) values("dream","male",1),("chimeng","female",4),("mengmeng","female",2),("drunkmeng","male",3);

# Query OK, 4 rows affected (0.13 sec)
# Records: 4  Duplicates: 0  Warnings: 0
  • 修改数据
update dep set id = 200 where id=2;
  • 查看数据
select * from dep;
+-----+-------------+--------------+
| id  | dep_name    | dep_desc     |
+-----+-------------+--------------+
|   1 | sm运动社    | 日常活动     |
|   3 | 技术部      | 能力提升     |
|   4 | cp外交部    | 社交沟通     |
| 200 | 游戏社      | 休闲娱乐     |
+-----+-------------+--------------+
4 rows in set (0.00 sec)
select * from emp;
+----+-----------+------------+--------+
| id | emp_name  | emp_gender | dep_id |
+----+-----------+------------+--------+
|  1 | dream     | male       |      1 |
|  2 | chimeng   | female     |      4 |
|  3 | mengmeng  | female     |    200 |
|  4 | drunkmeng | male       |      3 |
+----+-----------+------------+--------+
4 rows in set (0.00 sec)

【4】多对多关系

  • 书籍表的角度
    • 一本书可以有多个作者
  • 作者表的角度
    • 一个作者可以写多本书
  • 总结
    • 书籍表和作者表是双向的一对多
  • 那么关系就是 多对多 关系

(1)建表问题

  • 创建图书表
id title price author_id
create table book(
	id int primary key auto_increment,
    title varchar(32),
    price int,
    author_id int,
    foreign key(author_id) references author(id)
    on update cascade
    on delete cascade

)
  • 创建作者表
id name age book_id
create table author (
	id int primary key auto_increment,
    name varchar(32),
    age int,
    book_id int,
    foreign key(book_id) references book(id)
    on update cascade
    on delete cascade
)

这种方式建表,由于外键具有 在创建表的时候一定要先创建被关联表 的特性

导致都无法创建彼此的关联表

针对多对多字段关系,不能在原有两张表的基础上创建外键

需要创建一张新表来建立两表的关系

(2)解决循环建表问题

  • 建表
book
id title price

author
id name age

book_connect
id boo_id author_id
  • 创建表
# 图书表
create table book(
    id int primary key auto_increment, 
    title varchar(32), 
    price int
);

# 作者表
create table author(
	id int primary key auto_increment,
    name varchar(32),
    age int
);

# 中转联系表
create table book_connect(
	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
);
  • 查看表
desc book;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| title | varchar(32) | YES  |     | NULL    |                |
| price | int(11)     | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
desc author;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(32) | YES  |     | NULL    |                |
| age   | int(11)     | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
desc book_connect;
+-----------+---------+------+-----+---------+----------------+
| Field     | Type    | Null | Key | Default | Extra          |
+-----------+---------+------+-----+---------+----------------+
| id        | int(11) | NO   | PRI | NULL    | auto_increment |
| author_id | int(11) | YES  | MUL | NULL    |                |
| book_id   | int(11) | YES  | MUL | NULL    |                |
+-----------+---------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
  • 插入数据
insert into book(title,price) values("西游记",18),("水浒传",29),("三国演义",99),("如何让富婆爱上你",999);

insert into author(name,age) values("dream",18),("chimeng",28),("mengmeng",38);

insert into book_connect(author_id,book_id) values(1,3),(2,1),(2,3),(1,1);
  • 查看表数据
select * from book;
+----+--------------------------+-------+
| id | title                    | price |
+----+--------------------------+-------+
|  1 | 西游记                   |    18 |
|  2 | 水浒传                   |    29 |
|  3 | 三国演义                 |    99 |
|  4 | 如何让富婆爱上你         |   999 |
+----+--------------------------+-------+
4 rows in set (0.00 sec)
select * from author;
+----+----------+------+
| id | name     | age  |
+----+----------+------+
|  1 | dream    |   18 |
|  2 | chimeng  |   28 |
|  3 | mengmeng |   38 |
+----+----------+------+
3 rows in set (0.00 sec)
select * from book_connect;
+----+-----------+---------+
| id | author_id | book_id |
+----+-----------+---------+
|  1 |         1 |       3 |
|  2 |         2 |       1 |
|  3 |         2 |       3 |
|  4 |         1 |       1 |
+----+-----------+---------+
4 rows in set (0.00 sec)

【5】一对一关系

在MySQL的关系中没有多对一的说法

一对多 多对多 都叫 一对多

  • 如果一个表的字段特别多,每次查询又不是所有字段的数据都需要

示例一

  • 可以将表一分为二

    • 用户表
    • 用户详情表
  • 用户表

    • 一个用户能否对应多个用户详情
  • 详情表

    • 一个详情表能否属于多个用户
  • 结论

    • 单向的一对多都不能成立,那么这个时候两者之间的表关系要么是一对一,或没有关系

示例二

  • 客户表
  • 学生表

建表

authors
id name age author_detail_id

author_detail
id phone addr

一对一,外键建在任意一方都可以,但是建议建立在查询频率较高的表内

  • 创建表
create table author_detail(
	id int primary key auto_increment,
    phone int,
    addr varchar(64)
);

create table authors(
	id int primary key auto_increment,
    name varchar(16),
    age int,
    author_detail_id int unique,
    foreign key(author_detail_id) references author_detail(id)
    on update cascade
    on delete cascade
);
  • 查看表
desc author_detail;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| phone | int(11)     | YES  |     | NULL    |                |
| addr  | varchar(64) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
desc authors;
+------------------+-------------+------+-----+---------+----------------+
| Field            | Type        | Null | Key | Default | Extra          |
+------------------+-------------+------+-----+---------+----------------+
| id               | int(11)     | NO   | PRI | NULL    | auto_increment |
| name             | varchar(16) | YES  |     | NULL    |                |
| age              | int(11)     | YES  |     | NULL    |                |
| author_detail_id | int(11)     | YES  | UNI | NULL    |                |
+------------------+-------------+------+-----+---------+----------------+
4 rows in set (0.01 sec)

【6】小结

  • 表关系的建立需要用到 foreign key
  • 一对多
    • 外键字段在多的一方
  • 多对多
    • 开设第三张表作为媒介
  • 一对一
    • 建在任意一方均可
    • 推荐建在查询频率较高的表中
  • 判断表与表之间的关系要站在双方的角度考虑

【三】修改表

MySQL 的 SQL 语句是不区分大小写的

【1】修改表明

alter table 表名 rename 新表明;

【2】增加字段

# 默认添加到尾部
alter table 表名 add 字段名 字段类型(宽度) 约束条件;

# 添加到首位
alter table 表名 add 字段名 字段类型(宽度) 约束条件 first;

# 添加到指定字段名的后面
alter table 表名 add 字段名 字段类型(宽度) 约束条件 after 字段名;

【3】删除字段

# 修改指定字段名
alter table 表名 modify 字段名 字段类型(宽度) 约束条件;

# 替换指定字段名
alter table 表名 change 旧字段名 新字段名 字段类型(宽度) 约束条件;

【四】复制表

SQL 语句其实查询到的表都其实是虚拟表(在内存中)

【1】全复制表

# 只能复制表中的原始数据,但是无法复制每个字段的约束条件(主键、外键、索引...)
create table 表名 select * from 旧表名;

【2】根据条件复制表

# 根据查询条件复制旧表中的数据,如果有数据就会被复制过来,如果没有数据就会创建一张没有数据的空表
create table 表名 select * from 旧表名 where 条件; 
posted @ 2023-07-01 22:33  Chimengmeng  阅读(14)  评论(0编辑  收藏  举报