文章目录
- 表的增删改查
- 一、CRUD
- 1.新增(Create)
- 1.插入多行
- 2.指定列多行插入
- 3.插入datetime类型
- 4.插入当前时间
- 5.插入查询的结果
- 2.查询(Retrieve)
- 1.全列查询 *
- 2.指定列查询
- 3.查询字段为表达式
- 4.指定别名 as
- 5.去重 distinct
- 6.排序 order by
- 7.条件查询 where
- 8.分页查询:limit
- 3.修改(Update)
- 4.删除(Delete)
- 数据库的备份方式:
- 二、数据库约束
- not null
- unique:唯一的
- default:
- primary key 主键
- 如何保证主键唯一?
- foreign 外键
- 表的设计
表的增删改查
一、CRUD
1.新增(Create)
insert into 表名 values(值,值);
insert into student values(1,'zhangsan');
- 此处的值要和列(个数和类型)相匹配
- 如果只插入了一个name,id这一列就是默认值null
1.插入多行
个数和类型要和表结构匹配。
insert into 表名 values(值,值),(值,值),(值,值);
insert into techer values(1,'小明'),(3,'李四'),(4,'王五');
2.指定列多行插入
insert into 表名 (列名,列名...)values(值,值),(值,值),(值,值);
-- 插入两条记录,value_list 数量必须和指定列数量及顺序一致
INSERT INTO student (id, sn, name) VALUES
(102, 20001, '曹孟德'),
(103, 20002, '孙仲谋');
3.插入datetime类型
使用字符串来表示时间的日期
create table student (id int ,name varchar(20),birthday datetime);
insert into student values(1,'张三','2000-01-11 12:00:00');
4.插入当前时间
now()方法
insert into student values(2,'李四',now());
mysql> select * from student;
+------+------+---------------------+
| id | name | birthday |
+------+------+---------------------+
| 1 | 张三 | 2000-01-11 12:00:00 |
| 2 | 李四 | 2024-05-13 14:03:02 |
+------+------+---------------------+
5.插入查询的结果
- 查询的结果集合,列数和类型要和插入的表匹配。
mysql> select * from student;
+------+------+
| id | name |
+------+------+
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
+------+------+
3 rows in set (0.00 sec)
mysql> select * from student2;
Empty set (0.00 sec)
mysql> insert into student2 select *from student;
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from student2;
+------+------+
| id | name |
+------+------+
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
+------+------+
2.查询(Retrieve)
创建表并插入数据:
-- 创建考试成绩表
DROP TABLE IF EXISTS exam_result;
CREATE TABLE exam_result (
id INT,
name VARCHAR(20),
chinese DECIMAL(3,1),
math DECIMAL(3,1),
english DECIMAL(3,1)
);
-- 插入测试数据
INSERT INTO exam_result (id,name, chinese, math, english) VALUES
(1,'唐三藏', 67, 98, 56),
(2,'孙悟空', 87.5, 78, 77),
(3,'猪悟能', 88, 98.5, 90),
(4,'曹孟德', 82, 84, 67),
(5,'刘玄德', 55.5, 85, 45),
(6,'孙权', 70, 73, 78.5),
(7,'宋公明', 75, 65, 30);
1.全列查询 *
查询表中的所有行和所有列。
- 在生成环境下要谨慎使用。
select * from 表名;
mysql> select * from exam_result;
+------+--------+---------+------+---------+
| id | name | chinese | math | english |
+------+--------+---------+------+---------+
| 1 | 唐三藏 | 67.0 | 98.0 | 56.0 |
| 2 | 孙悟空 | 87.5 | 78.0 | 77.0 |
| 3 | 猪悟能 | 88.0 | 98.5 | 90.0 |
| 4 | 曹孟德 | 82.0 | 84.0 | 67.0 |
| 5 | 刘玄德 | 55.5 | 85.0 | 45.0 |
| 6 | 孙权 | 70.0 | 73.0 | 78.5 |
| 7 | 宋公明 | 75.0 | 65.0 | 30.0 |
+------+--------+---------+------+---------+
客户端发送请求给服务器,查询出来之后,服务器把查询到的结果,在网络中通过响应返回给客户端,并在客户端上打印出来。
如果表中的数据特别多时,可能会产生:
1.读取硬盘时,把硬盘的IO跑满了,此时程序的其他部分想访问硬盘,就会非常慢。
2.操作网络,可能会把网卡的带宽跑满,此时其他客户端想通过网络访问服务器,也会非常慢。
这样的拥堵,就有可能导致客户端无法顺利访问
2.指定列查询
- 按需求进行查询。
select 列名,列名...from 表名;
mysql> select name,math from exam_result;
+--------+------+
| name | math |
+--------+------+
| 唐三藏 | 98.0 |
| 孙悟空 | 78.0 |
| 猪悟能 | 98.5 |
| 曹孟德 | 84.0 |
| 刘玄德 | 85.0 |
| 孙权 | 73.0 |
| 宋公明 | 65.0 |
+--------+------+
3.查询字段为表达式
- 一边查询,一边进行计算(列和列之间的计算)
在查询的时候,写作由列名构成的表达式。把这一列中的所有行都代入到表达式中,参与运算。
- 并不会修改原始数据,展示的是临时表。只针对从数据库服务器查询出来的数据进行运算,不影响原有数据。
查询所有人语文分数-10的值
select name ,chinese-10 from exam_result;
+--------+------------+
| name | chinese-10 |
+--------+------------+
| 唐三藏 | 57.0 |
| 孙悟空 | 77.5 |
| 猪悟能 | 78.0 |
| 曹孟德 | 72.0 |
| 刘玄德 | 45.5 |
| 孙权 | 60.0 |
| 宋公明 | 65.0 |
+--------+------------+
查询每个人的总成绩:
mysql> select name, chinese + english + math from exam_result;
+--------+--------------------------+
| name | chinese + english + math |
+--------+--------------------------+
| 唐三藏 | 221.0 |
| 孙悟空 | 242.5 |
| 猪悟能 | 276.5 |
| 曹孟德 | 233.0 |
| 刘玄德 | 185.5 |
| 孙权 | 221.5 |
| 宋公明 | 170.0 |
+--------+--------------------------+
- SQL在查询的时候,可以进行一些简单的统计操作。
4.指定别名 as
- 查询的时候,给列/表达式/表 指定别名
select 表达式 as 别名 from 表名;
select name,chinese+math+english as sum from exam_result;
+--------+-------+
| name | sum |
+--------+-------+
| 唐三藏 | 221.0 |
| 孙悟空 | 242.5 |
| 猪悟能 | 276.5 |
| 曹孟德 | 233.0 |
| 刘玄德 | 185.5 |
| 孙权 | 221.5 |
| 宋公明 | 170.0 |
+--------+-------+
5.去重 distinct
- distinct修饰某个列/多个列
- 值相同的行,只会保留一个
distinct
select distinct math from exam_result;
select distinct name,math from exam_result;
6.排序 order by
- 把行进行排序。
- 仍然是临时数据,把查询到的结果进行排序,不改变原始结构。
要明确排序的规则:1.针对哪个列作为比较规则 2. 是升序还是降序
select 列名 from 表名 order by 列名 asc
-- 升序排序(默认)
select 列名 from 表名 order by 列名 desc;
-- 降序排序
select name,math from exam_result order by math;
+--------+------+
| name | math |
+--------+------+
| 宋公明 | 65.0 |
| 孙权 | 73.0 |
| 孙悟空 | 78.0 |
| 曹孟德 | 84.0 |
| 刘玄德 | 85.0 |
| 唐三藏 | 98.0 |
| 唐三藏 | 98.0 |
| 猪悟能 | 98.5 |
+--------+------+
mysql> select name,math from exam_result order by math desc;
-- 降序
+--------+------+
| name | math |
+--------+------+
| 猪悟能 | 98.5 |
| 唐三藏 | 98.0 |
| 唐三藏 | 98.0 |
| 刘玄德 | 85.0 |
| 曹孟德 | 84.0 |
| 孙悟空 | 78.0 |
| 孙权 | 73.0 |
| 宋公明 | 65.0 |
+--------+------+
mysql> select name,math from exam_result;
+--------+------+
| name | math |
+--------+------+
| 唐三藏 | 98.0 |
| 孙悟空 | 78.0 |
| 猪悟能 | 98.5 |
| 曹孟德 | 84.0 |
| 刘玄德 | 85.0 |
| 孙权 | 73.0 |
| 宋公明 | 65.0 |
| 唐三藏 | 98.0 |
+--------+------+
如果不加上order by,则不应该依赖上述顺序,是“无序的”
mysql> select name,math,chinese from exam_result order by chinese desc;
+--------+------+---------+
| name | math | chinese |
+--------+------+---------+
| 猪悟能 | 98.5 | 88.0 |
| 孙悟空 | 78.0 | 87.5 |
| 曹孟德 | 84.0 | 82.0 |
| 宋公明 | 65.0 | 75.0 |
| 孙权 | 73.0 | 70.0 |
| 唐三藏 | 98.0 | 67.0 |
| 刘玄德 | 85.0 | 55.5 |
| 唐三藏 | 98.0 | NULL |
+--------+------+---------+
8 rows in set (0.00 sec)
mysql> select name,math from exam_result order by chinese desc;
+--------+------+
| name | math |
+--------+------+
| 猪悟能 | 98.5 |
| 孙悟空 | 78.0 |
| 曹孟德 | 84.0 |
| 宋公明 | 65.0 |
| 孙权 | 73.0 |
| 唐三藏 | 98.0 |
| 刘玄德 | 85.0 |
| 唐三藏 | 98.0 |
+--------+------+
即使没有选择语文成绩,仍然可以按照语文成绩进行排序
对表达式运算的结果进行排序:
mysql> select name,chinese+math+english as total from exam_result order by total;
-- 对表达式运算的结果进行排序
+--------+-------+
| name | total |
+--------+-------+
| 唐三藏 | NULL |
| 宋公明 | 170.0 |
| 刘玄德 | 185.5 |
| 唐三藏 | 221.0 |
| 孙权 | 221.5 |
| 曹孟德 | 233.0 |
| 孙悟空 | 242.5 |
| 猪悟能 | 276.5 |
+--------+-------+
指定多个列来排序。order by后面写多个列,使用,分隔开。
mysql> select * from exam_result order by math,chinese;
-- 先按照数学成绩来排序,如果数学成绩相同,则按照语文成绩排序
+------+--------+---------+------+---------+
| id | name | chinese | math | english |
+------+--------+---------+------+---------+
| 7 | 宋公明 | 75.0 | 65.0 | 30.0 |
| 6 | 孙权 | 70.0 | 73.0 | 78.5 |
| 2 | 孙悟空 | 87.5 | 78.0 | 77.0 |
| 4 | 曹孟德 | 82.0 | 84.0 | 67.0 |
| 5 | 刘玄德 | 55.5 | 85.0 | 45.0 |
| 10 | 唐三藏 | NULL | 98.0 | NULL |
| 1 | 唐三藏 | 67.0 | 98.0 | 56.0 |
| 3 | 猪悟能 | 88.0 | 98.5 | 90.0 |
+------+--------+---------+------+---------+
7.条件查询 where
- 会指定具体的条件,按照条件对数据进行筛选。
- where:遍历这个表的每一行记录,把每一行的数据分别代入条件中。如果条件成立,则会把数据放进结果集合中。
select 列名 from 表名 where 条件;
比较运算符:
- sql中没有==,而是使用=来比较相等(null不安全 null=null的结果是null.null参与的运算结果也是null)
- <=> 比较相等 (null安全 null<=>null的结果是true)
- != 、 <> 不等
- between a1 and a2 : 范围[a1,a2] 如果 a1<= value <=a2 ,返回true
- in(option…) :当前值如果是option中任意一种情况,返回true
- like : 模糊匹配 %表示任意多个任意字符;_表示任意一个字符
逻辑运算符:
- and 优先级 高于or 。在同时使用时,需要小括号来区别。
-- 基本查询
-- 查询英语不及格的同学及英语成绩 ( < 60 )
mysql> select name,english from exam_result where english<60;
+--------+---------+
| name | english |
+--------+---------+
| 唐三藏 | 56.0 |
| 刘玄德 | 45.0 |
| 宋公明 | 30.0 |
+--------+---------+
-- 查询语文成绩好于英语成绩的同学
select name,chinese,english from exam_result where chinese>english;
+--------+---------+---------+
| name | chinese | english |
+--------+---------+---------+
| 唐三藏 | 67.0 | 56.0 |
| 孙悟空 | 87.5 | 77.0 |
| 曹孟德 | 82.0 | 67.0 |
| 刘玄德 | 55.5 | 45.0 |
| 宋公明 | 75.0 | 30.0 |
+--------+---------+---------+
-- 查询总分在 200 分以下的同学
select name,math+chinese+english as total from exam_result where chinese+math+english<200;
-- where条件可以使用表达式,但是不能使用别名
+--------+-------+
| name | total |
+--------+-------+
| 刘玄德 | 185.5 |
| 宋公明 | 170.0 |
+--------+-------+
where条件可以使用表达式,但是不能使用别名
select条件查询执行的顺序:
1.遍历表中的每一个记录
2.把当前记录的值,代入条件,根据条件进行筛选
3.如果这个记录成立,就要保留,进行列上的表达式计算
4.如果有order by,会在所有行都被获取到之后(表达式也算完了)再针对所有的结果进行排序。
第三步定于的别名,where是第二部执行的
and or
-- 查询语文成绩大于80分,且英语成绩大于80分的同学
mysql> select name,english,chinese from exam_result where chinese>80 and english >80;
+--------+---------+---------+
| name | english | chinese |
+--------+---------+---------+
| 猪悟能 | 90.0 | 88.0 |
+--------+---------+---------+
-- 查询语文成绩大于80分,或英语成绩大于80分的同学
mysql> select name,english,chinese from exam_result where chinese>80 or english >80;
+--------+---------+---------+
| name | english | chinese |
+--------+---------+---------+
| 孙悟空 | 77.0 | 87.5 |
| 猪悟能 | 90.0 | 88.0 |
| 曹孟德 | 67.0 | 82.0 |
+--------+---------+---------+
-- 观察AND 和 OR 的优先级:
mysql> SELECT * FROM exam_result WHERE chinese > 80 or math>70 and english > 70;
+------+--------+---------+------+---------+
| id | name | chinese | math | english |
+------+--------+---------+------+---------+
| 2 | 孙悟空 | 87.5 | 78.0 | 77.0 |
| 3 | 猪悟能 | 88.0 | 98.5 | 90.0 |
| 4 | 曹孟德 | 82.0 | 84.0 | 67.0 |
| 6 | 孙权 | 70.0 | 73.0 | 78.5 |
+------+--------+---------+------+---------+
4 rows in set (0.00 sec)
mysql> SELECT * FROM exam_result WHERE (chinese > 80 or math>70) and english > 70;
+------+--------+---------+------+---------+
| id | name | chinese | math | english |
+------+--------+---------+------+---------+
| 2 | 孙悟空 | 87.5 | 78.0 | 77.0 |
| 3 | 猪悟能 | 88.0 | 98.5 | 90.0 |
| 6 | 孙权 | 70.0 | 73.0 | 78.5 |
+------+--------+---------+------+---------+
between and
-- 查询语文成绩在 [80, 90] 分的同学及语文成绩
mysql> select name,chinese from exam_result where chinese between 80 and 90;
+--------+---------+
| name | chinese |
+--------+---------+
| 孙悟空 | 87.5 |
| 猪悟能 | 88.0 |
| 曹孟德 | 82.0 |
+--------+---------+
-- 使用 AND 也可以实现
mysql> select name,chinese from exam_result where chinese >=80 and chinese <=90;
+--------+---------+
| name | chinese |
+--------+---------+
| 孙悟空 | 87.5 |
| 猪悟能 | 88.0 |
| 曹孟德 | 82.0 |
+--------+---------+
in
-- 查询数学成绩是 58 或者 59 或者 98 或者 99 分的同学及数学成绩
mysql> select name,math from exam_result where math in(58,59,98,99);
+--------+------+
| name | math |
+--------+------+
| 唐三藏 | 98.0 |
| 唐三藏 | 98.0 |
+--------+------+
-- 使用 OR 也可以实现
mysql> SELECT name, math FROM exam_result WHERE math = 58 OR math = 59 OR math
-> = 98 OR math = 99;
+--------+------+
| name | math |
+--------+------+
| 唐三藏 | 98.0 |
| 唐三藏 | 98.0 |
+--------+------+
模糊查询:like
-- % 匹配任意多个(包括 0 个)字符
mysql> select name from exam_result where name like '孙%';
+--------+
| name |
+--------+
| 孙悟空 |
| 孙权 |
+--------+
-- _ 匹配严格的一个任意字符
mysql> select name from exam_result where name like '孙_';
+------+
| name |
+------+
| 孙权 |
+------+
mysql> select name from exam_result where name like '孙__';
+--------+
| name |
+--------+
| 孙悟空 |
+--------+
NULL 的查询:IS [NOT] NULL
select * from exam_result where chinese = null;
-- =的话,查询到的还是空
Empty set (0.00 sec)
mysql> select * from exam_result where chinese <=> null;
+------+--------+---------+------+---------+
| id | name | chinese | math | english |
+------+--------+---------+------+---------+
| 10 | 唐三藏 | NULL | 98.0 | NULL |
+------+--------+---------+------+---------+
mysql> select * from exam_result where chinese <=> english;
+------+--------+---------+------+---------+
| id | name | chinese | math | english |
+------+--------+---------+------+---------+
| 10 | 唐三藏 | NULL | 98.0 | NULL |
+------+--------+---------+------+---------+
1 row in set (0.00 sec)
mysql> select * from exam_result where chinese is null;
-- is null只能顾及到一个列
+------+--------+---------+------+---------+
| id | name | chinese | math | english |
+------+--------+---------+------+---------+
| 10 | 唐三藏 | NULL | 98.0 | NULL |
+------+--------+---------+------+---------+
1 row in set (0.00 sec)
8.分页查询:limit
-
使用select * 这种查询方式,比较危险,要保障一次查询的数量有限,避免堵塞。
-
limit可以限制这次查询最多能查出多少个结果
mysql> select * from exam_result limit 3;
mysql> select * from exam_result limit 3 offset 0;
-- 显示前三条记录
-- limit 表示这次查询查几条记录
-- offset:偏移量,也就是一个下标,从0开始
+------+--------+---------+------+---------+
| id | name | chinese | math | english |
+------+--------+---------+------+---------+
| 1 | 唐三藏 | 67.0 | 98.0 | 56.0 |
| 2 | 孙悟空 | 87.5 | 78.0 | 77.0 |
| 3 | 猪悟能 | 88.0 | 98.5 | 90.0 |
+------+--------+---------+------+---------+
mysql> select * from exam_result limit 3 offset 3;
+------+--------+---------+------+---------+
| id | name | chinese | math | english |
+------+--------+---------+------+---------+
| 4 | 曹孟德 | 82.0 | 84.0 | 67.0 |
| 5 | 刘玄德 | 55.5 | 85.0 | 45.0 |
| 6 | 孙权 | 70.0 | 73.0 | 78.5 |
+------+--------+---------+------+---------+
mysql> select * from exam_result limit 3 offset 6;
+------+--------+---------+------+---------+
| id | name | chinese | math | english |
+------+--------+---------+------+---------+
| 7 | 宋公明 | 75.0 | 65.0 | 30.0 |
| 10 | 唐三藏 | NULL | 98.0 | NULL |
+------+--------+---------+------+---------+
3.修改(Update)
update 表名 set 列名 = 值 where 条件;
-- 将孙悟空同学的数学成绩变更为 80 分
mysql> update exam_result set math = 80 where name = '孙悟空';
-- 将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分
mysql> update exam_result set math = 60,chinese = 70 where name = '曹孟德';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
-- 将总成绩倒数前三的 3 位同学的数学成绩减上 30 分
update exam_result set math = math - 30 order by math+chinese+english limit 3;
4.删除(Delete)
delete from 表名 where 条件/ order by / limit;
- 把符合条件的行,从表中删除掉。
-- 删除孙悟空同学的考试成绩
delete from exam_result where name = '孙悟空';
-- 删除整张表数据
delete from exam_result ;-- (清空整张表->空表)
drop table exam_result; -- (删除表信息,表没了)
-- 准备测试表
DROP TABLE IF EXISTS for_delete;
CREATE TABLE for_delete (
id INT,
name VARCHAR(20)
);
-- 插入测试数据
INSERT INTO for_delete (name) VALUES ('A'), ('B'), ('C');
-- 删除整表数据
DELETE FROM for_delete;
数据库的备份方式:
1.数据库的数据最终是以文件(二进制)的形式,存储在硬盘上。将文件之间拷贝到新的机器上(全量备份)
2.mysqldump工具,将mysql中的数据导出成一系列insert语句,再把这些insert 语句放在新的mysql上执行。(全量&增量)
3.mysql的binlog功能,把mysql的各种操作,都通过日志记录下来,借住binlog,让另一个数据库按照binlog的内容执行(增量备份/实时备份)
二、数据库约束
有的时候,数据库中的数据,是有一定要求的。有些数据认为是合法数据,有些是非法的数据。数据库会自动的对数据的合法性进行校验检查。目的就是为了保证数据库中避免被插入/修改一些非法的数据。
- not null :表示某列不能填空值。
- unique : 表示某列的某行必须有唯一的值,不能重复。
- default : 设置默认值。
- primary key 主键 : 唯一标识(not null + unique)
- foreign key 外键: 保证一个表中的数据匹配另一个表中的值的参照完整性。
not null
mysql> create table student(id int not null,name varchar(20));
Query OK, 0 rows affected (0.01 sec)
mysql> insert into student values(null,null);
ERROR 1048 (23000): Column 'id' cannot be null
mysql> update student set id = null where name = '张三';
ERROR 1048 (23000): Column 'id' cannot be null
unique:唯一的
- unique约束,会让后续插入数据/修改数据的时候,都先触发一次查询操作。通过查询来确定当前记录是否已经存在
- 引入约束后,执行效率就会受到影响,可能会降低很多。
mysql> create table student(id int unique,name varchar(20));
Query OK, 0 rows affected (0.01 sec)
mysql> insert into student values(1,'张三');
Query OK, 1 row affected (0.00 sec)
mysql> insert into student values(1,'张三');
ERROR 1062 (23000): Duplicate entry '1' for key 'id'
-- 重复 -- 条目
default:
- 描述某一列的默认值. 默认的默认值是null,可以通过default约束来修改默认值。
mysql> desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | UNI | NULL | |
| name | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
mysql> create table student(id int ,name varchar(20) default '未命名');
Query OK, 0 rows affected (0.01 sec)
mysql> desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | 未命名 | |
+-------+-------------+------+-----+---------+-------+
alter table 可以修改表的结构,进而修改约束
primary key 主键
-
一行记录的身份标识
-
一张表只能有一个主键。
-
主键不一定只有一个列,可以用多个列共同构成一个主键(联合主键)
-
带有主键的表,每次插入/修改数据,也会先进行查询的操作。
mysql会把带有unique和primary key的列自动生成索引,从而加快查询的速度。
mysql> create table student(id int primary key,name varchar(20));
Query OK, 0 rows affected (0.01 sec)
mysql> desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
如何保证主键唯一?
mysql提供了一种“自增主键”的机制。主键经常会使用int/bigint来进行设置。程序员在插入数据的时候,不必手动指定主键的值,由数据库服务器自动分配一个主键。从1开始,依次递增的分配主键的值。
mysql> create table student(id int primary key auto_increment,name varchar(20));
Query OK, 0 rows affected (0.00 sec)
mysql> desc student;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
mysql> insert into student values(null,'张三');
-- 不设置id,让自增主键自行分配
Query OK, 1 row affected (0.01 sec)
mysql> insert into student values(null,'张三');
Query OK, 1 row affected (0.01 sec)
mysql> select * from student;
+----+------+
| id | name |
+----+------+
| 1 | 张三 |
| 2 | 张三 |
+----+------+
mysql> insert into student values(10,'李四');
Query OK, 1 row affected (0.01 sec)
-- 从最大值开始,后续自动分配
-- 相当于使用了一个变量,保存了表的最大id值,后续根据最大id来进行自增分配
mysql> insert into student values(null,'王五');
Query OK, 1 row affected (0.01 sec)
mysql> select * from student;
+----+------+
| id | name |
+----+------+
| 1 | 张三 |
| 2 | 张三 |
| 3 | 李四 |
| 10 | 李四 |
| 11 | 王五 |
+----+------+
这里的自动分配具有局限性,如果是单个的mysql服务器,是没有问题的。但是如果是一个分布式系统,有多个mysql服务器构成的集群,就不能依靠自增主键了。
要保证在分布式的musql服务器中,其中一个主机存储的id,具有唯一性。往往要进行一定的算法处理。可以运用时间戳+机房编号/主机编号+随机因子的字符串拼贴,来得到唯一的id.
foreign 外键
-
描述了两个表之间的关联关系
class(classid ,name) 2101 计科 2102 计科 2103 计科 student(id ,name,classid) 01 张三 2101 02 李四 2102 05 王五 2107(不在class表中)
class表中的数据,约束了student表中的数据。
create table student(id int primary key,name varchar(20),classid int,foreign key(classid) references class(classid));
把class表称为父表(约束别人),把student表称为子表(被别人约束)
mysql> create table class(classid int primary key,name varchar(20));
Query OK, 0 rows affected (0.01 sec)
mysql> insert into class values(2101,'计科1班'),(2102,'计科2班'),(2103,'计科3班');
create table student(id int primary key,name varchar(20),classid int,foreign key(classid) references class(classid));
mysql> insert into student values (1,'张三',2101);
Query OK, 1 row affected (0.01 sec)
mysql> insert into student values (2,'李四',2109);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`day5_14`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`classid`) REFERENCES `class` (`classid`))
-
references 引用,表示这一列的数据出自另一个表的那一列
-
如果针对父表进行修改/删除 操作,如果当前要操作的值已经被子表引用了,就会操作失败。
-
外键要始终保持,子表的数据在对应的父表的列中始终存在。
在操作子表时,要保证在父表的范围内。操作父表时,要保证没有被子表引用。同理,如果父表已经被子表引用,就无法进行父表的删除。只能先删子表,再删父表。
- 指定外键约束的时候,要求父表中被该关联的这一列,必须是主键或者是unique。
表的设计
根据实际的场景需求,明确当前要创建几个表,每个表的内容和表之间的联系
1.梳理清楚 需求中的“实体”(对象)
每个实体都需要安排一个表,表的列对应到实体的各个属性。
2.确定好实体之间的“关系”
1对1、1对多、多对多
点击移步博客主页,欢迎光临~