数据库约束
主键约束
#创建表,把id设为主键
mysql> create table test02(
-> id int primary key, #----主键约束
-> name varchar(50)
-> );
Query OK, 0 rows affected (0.02 sec)
#插入数据测试
mysql> insert into test02 values(1,"成都");
Query OK, 1 row affected (0.01 sec)
mysql> insert into test02 values(1,"西安");
ERROR 1062 (23000): Duplicate entry '1' for key 'test02.PRIMARY'
mysql> insert into test02 values(null,"西安");
ERROR 1048 (23000): Column 'id' cannot be null
mysql> insert into test02 values(2,"西安");
Query OK, 1 row affected (0.00 sec)
#主键自动增加auto_increment
mysql> create table test02(
-> id int primary key auto_increment,
-> name varchar(50)
-> );
Query OK, 0 rows affected (0.02 sec)
#插入数据测试
mysql> insert into test02 values(1,"成都");
Query OK, 1 row affected (0.00 sec)
mysql> insert into test02 values(1,"西安");
ERROR 1062 (23000): Duplicate entry '1' for key 'test02.PRIMARY'
mysql> insert into test02 values(null,"西安");
Query OK, 1 row affected (0.01 sec)
mysql> insert into test02 values(2,"西安");
ERROR 1062 (23000): Duplicate entry '2' for key 'test02.PRIMARY'
mysql> insert into test02 values(3,"西安");
Query OK, 1 row affected (0.01 sec)
mysql> select * from test02;
+----+--------+
| id | name |
+----+--------+
| 1 | 成都 |
| 2 | 西安 |
| 3 | 西安 |
+----+--------+
3 rows in set (0.00 sec)
#主键另外一种写法
mysql> create table test02(
-> id int auto_increment,
-> name varchar(50),
-> primary key(id)
-> );
Query OK, 0 rows affected (0.02 sec)
唯一约束
mysql> create table test02(
-> id int primary key auto_increment,
-> name varchar(50) unique #---唯一约束
-> );
Query OK, 0 rows affected (0.04 sec)
#插入数据测试
mysql> insert into test02 values(1,"成都");
Query OK, 1 row affected (0.01 sec)
mysql> insert into test02 values(2,"成都");
ERROR 1062 (23000): Duplicate entry '成都' for key 'test02.name'
mysql> insert into test02 values(2,"西安");
Query OK, 1 row affected (0.00 sec)
mysql> select * from test02;
+----+--------+
| id | name |
+----+--------+
| 1 | 成都 |
| 2 | 西安 |
+----+--------+
2 rows in set (0.00 sec)
# 另一种写法
create table tets02(
-> id int auto_increment,
-> name varchar(50),# ---唯一约束
-> primary key(id),
-> unique(name)
-> );
Query OK, 0 rows affected (0.02 sec)
默认值约束
mysql> create table test02(
-> id int primary key auto_increment,
-> name varchar(50) unique,
-> age int default 18
-> );
Query OK, 0 rows affected (0.04 sec)
#插入数据测试
mysql> insert into test02 values(1,"小红",20);
Query OK, 1 row affected (0.01 sec)
mysql> insert into test02 values(default,"小蓝",19); #---因为存在自增,所以可以写默认
Query OK, 1 row affected (0.00 sec)
mysql> insert into test02(name) values("小黄");
Query OK, 1 row affected (0.00 sec)
mysql> select * from test02;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 小红 | 20 |
| 2 | 小蓝 | 19 |
| 3 | 小黄 | 18 |
+----+--------+------+
3 rows in set (0.00 sec)
非空约束
mysql> create table test02(
-> id int primary key auto_increment,
-> name varchar(50) unique not null,
-> age int default 18,
-> password varchar(255) not null
-> );
Query OK, 0 rows affected (0.03 sec)
mysql> insert into test02 values(1,"小兰",23,"890890");
Query OK, 1 row affected (0.01 sec)
mysql> insert into test02 values(2,"小二",18,null);
ERROR 1048 (23000): Column 'password' cannot be null
检查约束
mysql> create table test02(
-> id int primary key auto_increment,
-> name varchar(50) not null unique,
-> age int check(age >= 18)
-> );
Query OK, 0 rows affected (0.03 sec)
mysql> insert into test02 value(null,"张三",20);
Query OK, 1 row affected (0.01 sec)
mysql> insert into test02 value(null,"李四",17);
ERROR 3819 (HY000): Check constraint 'test02_chk_1' is violated.
mysql>
修改表结构
修改列类型
ALTER TABLE 表名 MODIFY 列名 列类型; -- 注意存在值的情况,类型不一定能成功
增加列
ALTER TABLE 表名 ADD 列名 列类型;
删除列
ALTER TABLE 表名 DROP 列名;
列改名
ALTER TABLE 表名 CHANGE 旧列名 新列名 列类型;
更改表名
ALTER TABLE 表名 RENAME 新表名;
RENAME TABLE 表名 TO 新表名;
mysql> alter table test02 modify age varchar(20);
Query OK, 1 row affected (0.07 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> alter table test02 add address varchar(50);
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> select * from test02;
+----+--------+------+---------+
| id | name | age | address |
+----+--------+------+---------+
| 1 | 张三 | 20 | NULL |
+----+--------+------+---------+
1 row in set (0.00 sec)
mysql> alter table test02 drop age;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> select * from test02;
+----+--------+---------+
| id | name | address |
+----+--------+---------+
| 1 | 张三 | NULL |
+----+--------+---------+
1 row in set (0.00 sec)
mysql> alter table test02 change address age int;
Query OK, 1 row affected (0.07 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from test02;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 张三 | NULL |
+----+--------+------+
1 row in set (0.00 sec)
mysql> alter table test02 rename test03;
Query OK, 0 rows affected (0.02 sec)
mysql> rename table test03 to test02;
Query OK, 0 rows affected (0.01 sec)
复制表结构和内容
#查看test02的内容
mysql> select * from test02;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 张三 | NULL |
+----+--------+------+
1 row in set (0.00 sec)
# 复制test02的表结构给test03,不复制内容
mysql> create table test03 like test02;
Query OK, 0 rows affected (0.03 sec)
mysql> show tables;
+-----------------+
| Tables_in_db_ck |
+-----------------+
| t_hero |
| test02 |
| test03 |
+-----------------+
3 rows in set (0.00 sec)
mysql> desc test03;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(50) | NO | UNI | NULL | |
| age | int | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
mysql> select * from test03;
Empty set (0.00 sec)
mysql> drop table test03;
Query OK, 0 rows affected (0.02 sec)
#复制test02的表内容给test03,不复制结构
mysql> create table test03 select * from test02;
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> show tables;
+-----------------+
| Tables_in_db_ck |
+-----------------+
| t_hero |
| test02 |
| test03 |
+-----------------+
3 rows in set (0.00 sec)
mysql> select * from test03;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 张三 | NULL |
+----+--------+------+
1 row in set (0.00 sec)
mysql> desc test03;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int | NO | | 0 | |
| name | varchar(50) | NO | | NULL | |
| age | int | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
增加语句
mysql> select * from test02;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 张三 | NULL |
+----+--------+------+
1 row in set (0.00 sec)
mysql> insert into test02 value(null,"小红",18);
Query OK, 1 row affected (0.00 sec)
mysql> insert into test02(name,age) value("小蓝",20);
Query OK, 1 row affected (0.00 sec)
mysql> insert into test02(age,name) value(21,"小绿");
Query OK, 1 row affected (0.00 sec)
mysql> insert into test02(name,age) value("小羊",11),("小牛",22);
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from test02;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 张三 | NULL |
| 2 | 小红 | 18 |
| 3 | 小蓝 | 20 |
| 4 | 小绿 | 21 |
| 5 | 小羊 | 11 |
| 6 | 小牛 | 22 |
+----+--------+------+
6 rows in set (0.00 sec)
删除语句和truncate
删除语言,请注意删除的条件!!!如果不带条件,则删除全表。
语法结构
delete from table_name [where 条件];
truncate table table_name;
mysql> select * from test02;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 张三 | NULL |
| 2 | 小红 | 18 |
| 3 | 小蓝 | 20 |
| 4 | 小绿 | 21 |
| 5 | 小羊 | 11 |
| 6 | 小牛 | 22 |
+----+--------+------+
6 rows in set (0.00 sec)
mysql> delete from test02 where id=3;
Query OK, 1 rows affected (0.01 sec)
mysql> select * from test02;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 张三 | NULL |
| 2 | 小红 | 18 |
| 4 | 小绿 | 21 |
| 5 | 小羊 | 11 |
| 6 | 小牛 | 22 |
+----+--------+------+
5 rows in set (0.00 sec)
-- 如果没有条件,则清空全表数据【慎重!!】
delete from test02;
-- truncate清空全表[注意:truncate删除数据是不经过数据字典]
truncate table test02;
更新语句
更新就是修改表中的数据。
语法结构
update table_name set 字段1=新值 [, 字段2=新值, 字段3=字段3 + 1] [where 条件];
mysql> select * from test02;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 小红 | 18 |
| 2 | 小蓝 | 20 |
| 3 | 小绿 | 21 |
| 4 | 小羊 | 34 |
| 5 | 小牛 | 22 |
+----+--------+------+
5 rows in set (0.00 sec)
mysql> update test02 set age=23 where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update test02 set age=age+10;
Query OK, 5 rows affected (0.00 sec)
Rows matched: 5 Changed: 5 Warnings: 0
mysql> select * from test02;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 小红 | 33 |
| 2 | 小蓝 | 30 |
| 3 | 小绿 | 31 |
| 4 | 小羊 | 44 |
| 5 | 小牛 | 32 |
+----+--------+------+
5 rows in set (0.00 sec)
replace语句
该语句是集更新和插入为一体的一个语句。
如果表中没有这条数据,则执行插入,否则执行更新
mysql> replace into test02 values(1,"小红",100);
Query OK, 2 rows affected (0.00 sec)
mysql> select * from test02;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 小红 | 100 |
| 2 | 小蓝 | 30 |
| 3 | 小绿 | 31 |
| 4 | 小羊 | 44 |
| 5 | 小牛 | 32 |
+----+--------+------+
5 rows in set (0.00 sec)
select查询语句
在开发中,查询语句是使用最多,也是CRUD中,复杂度最高的sql语句。
查询的语法结构
select *|字段1 [, 字段2 ……] from 表名称 [, 表名称2……] [where 条件] [group by 字段 [having 分组后的筛选]] [order by 字段 [desc|asc] [字段2 [desc|asc] ……]] [limit 分页]
简单的sql查询
#查询所有数据
select * from test02;
#查询需要的字段信息
select id,name from test02;
# 查询一个字段,一个等值条件
select name from test02 where id=1;
补充:+ 说明
-- MySQL的+默认只有一个功能:运算符
SELECT 100+80; # 结果为180
SELECT '123'+80; # 只要其中一个为数值,则试图将字符型转换成数值,转换成功做预算,结果为203
SELECT 'abc'+80; # 转换不成功,则字符型数值为0,结果为80
SELECT 'This'+'is'; # 转换不成功,结果为0
SELECT 'This'+'30is'; # ?猜测下这个结果是多少?
SELECT NULL+80; # 只要其中一个为NULL,则结果为NULL
等值判断
条件中,出现了相等值的判断,一般采用=
进行判断。
=
判断两次的值是否相等is
判断空nullis not null
来判断不为空<=>
可以判断null或者普通值
不等判断
!=
不等于<>
也是不等于
逻辑运算符
逻辑运算符是多条件关联的一种方式。
与或非
and
or
not
注意:在sql中,如果要提升条件的运行顺序,或者提高条件的优先级别,则需要使用括号来提升。
结果排序
# 语法结构
order by 字段
order by 字段 asc|desc;
order by 字段 asc|desc, 字段2 ;
mysql> select * from test02;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 小红 | 100 |
| 2 | 小蓝 | 30 |
| 3 | 小绿 | 31 |
| 4 | 小羊 | 44 |
| 5 | 小牛 | 32 |
+----+--------+------+
5 rows in set (0.00 sec)
mysql> select * from test02 order by age;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 2 | 小蓝 | 30 |
| 3 | 小绿 | 31 |
| 5 | 小牛 | 32 |
| 4 | 小羊 | 44 |
| 1 | 小红 | 100 |
+----+--------+------+
5 rows in set (0.00 sec)
mysql> select * from test02 order by age asc;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 2 | 小蓝 | 30 |
| 3 | 小绿 | 31 |
| 5 | 小牛 | 32 |
| 4 | 小羊 | 44 |
| 1 | 小红 | 100 |
+----+--------+------+
5 rows in set (0.00 sec)
mysql> select * from test02 order by age desc;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 小红 | 100 |
| 4 | 小羊 | 44 |
| 5 | 小牛 | 32 |
| 3 | 小绿 | 31 |
| 2 | 小蓝 | 30 |
+----+--------+------+
5 rows in set (0.00 sec)
mysql> select * from test02 order by age,id desc;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 2 | 小蓝 | 30 |
| 3 | 小绿 | 31 |
| 5 | 小牛 | 32 |
| 4 | 小羊 | 44 |
| 1 | 小红 | 100 |
+----+--------+------+
5 rows in set (0.00 sec)
分页功能
select语句,查询数据时,可能结果会非常多,此时就不能直接展示,分页展示。
总数量(all_data):查询 select count(*)
每页展示的数量(page_size):程序员定
当前页(cur_page):默认第一页,用户自己点击选择
总页数(all_page):总数量 % 每页的数量 == 0 整除后的商 : 商 + 1
mysql> select * from test02 limit 2;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 小红 | 100 |
| 2 | 小蓝 | 30 |
+----+--------+------+
2 rows in set (0.00 sec)
mysql> select * from test02 limit 3,2;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 4 | 小羊 | 44 |
| 5 | 小牛 | 32 |
+----+--------+------+
2 rows in set (0.00 sec)
为什么分表
数据直接都存储在一张表中:
如果数据很大,性能会出现问题
将不同的数据,如果放在同一个表中,可能数据冗余
数据冗余,会导致数据可能出错
将不同的类型,采用不同的数据表进行存储,如果两张表或者多张表之间存在关联关系,则可以采用外键来描述这种关联关系。
主表中,一般是一个字段,改字段一般是从表的主键。
mysql> create table grade(
-> id int auto_increment,
-> name varchar(50) unique,
-> primary key(id)
-> );
Query OK, 0 rows affected (0.03 sec)
mysql> insert into grade(name) value("Java精品班"), ("python数据分析班"), ("网络安全班"), ("云原生高级班");
Query OK, 4 rows affected (0.01 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> create table student(
-> id int primary key auto_increment,
-> name varchar(50) unique,
-> class_id int
-> );
Query OK, 0 rows affected (0.03 sec)
mysql> desc student;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(50) | YES | UNI | NULL | |
| class_id | int | YES | | NULL | |
+----------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
mysql> insert into student(name, class_id) values("张三", 1);
Query OK, 1 row affected (0.01 sec)
mysql> insert into student(name, class_id) values("张三2", 3);
Query OK, 1 row affected (0.00 sec)
mysql> insert into student(name, class_id) values("张三3", 2);
Query OK, 1 row affected (0.01 sec)
mysql> select * from student;
+----+---------+----------+
| id | name | class_id |
+----+---------+----------+
| 1 | 张三 | 1 |
| 2 | 张三2 | 3 |
| 3 | 张三3 | 2 |
+----+---------+----------+
3 rows in set (0.00 sec)
mysql> select * from grade;
+----+-----------------------+
| id | name |
+----+-----------------------+
| 1 | Java精品班 |
| 2 | python数据分析班 |
| 4 | 云原生高级班 |
| 3 | 网络安全班 |
+----+-----------------------+
4 rows in set (0.00 sec)
外键和多表关联
外键:指的是两张或者多张表之间关联关系的字段。
外键约束:是表的约束,是约束表在插入外键数据时能够正确的插入。
如何添加约束:
# 在创建表的同时,将外键约束添加上去
# 首先保证班级表创建成功
# 插入正确的数据
create table grade(
id int auto_increment,
name varchar(50) unique,
primary key(id)
)
insert into grade(name) value("Java精品班"), ("python数据分析班"), ("网络安全班"), ("云原生高级班");
外键约束
外键是构建于一个表的两个字段或者两个表的两个字段之间的关系
外键确保了相关的两个字段的两个关系:
子(从)表外键列的值必须在主表参照列值的范围内,或者为空(也可以加非空约束,强制不允许为空)。
当主表的记录被子表参照时,主表记录不允许被删除。
外键参照的只能是主表主键或者唯一键,保证子表记录可以准确定位到被参照的记录。
ALTER TABLE 表名 ADD CONSTRAINT 外键名 FOREIGN KEY(外键字段名)
REFERENCES 外表表名(主键字段名)
[ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
[ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
格式FOREIGN KEY (外键列名)REFERENCES 主表(参照列)
表与表之间的关联关系
当表与表之间存在了外键,这就意味着,这两张表之间存在某种关联关系。
一旦表存在了关联关系,则会进行外键设计,如果设计外键,将外键设计在哪张表中?
一对一 :外键可以设计在任意一张表中
一对多 :外键必须设计在多方
多对多 :创建第三张表,来专门描述两张表的关联关系
多表关联查询
当两张或者多张表之间存在了关联关系,往往多表查询,如果查询。
交叉连接
内连接
外链接
左外连接
右外连接
自连接
全连接
select *|字段 [,……] from 表名称 [,表名称] ……
#-- 交叉连接(cross join)
#-- 在查询多表时,不指定表的关联关系,数据只能全部匹配
#-- 引发笛卡尔积现象
mysql> select * from student,grade;
+----+---------+----------+----+-----------------------+
| id | name | class_id | id | name |
+----+---------+----------+----+-----------------------+
| 3 | 张三3 | 2 | 1 | Java精品班 |
| 2 | 张三2 | 3 | 1 | Java精品班 |
| 1 | 张三 | 1 | 1 | Java精品班 |
| 3 | 张三3 | 2 | 2 | python数据分析班 |
| 2 | 张三2 | 3 | 2 | python数据分析班 |
| 1 | 张三 | 1 | 2 | python数据分析班 |
| 3 | 张三3 | 2 | 4 | 云原生高级班 |
| 2 | 张三2 | 3 | 4 | 云原生高级班 |
| 1 | 张三 | 1 | 4 | 云原生高级班 |
| 3 | 张三3 | 2 | 3 | 网络安全班 |
| 2 | 张三2 | 3 | 3 | 网络安全班 |
| 1 | 张三 | 1 | 3 | 网络安全班 |
+----+---------+----------+----+-----------------------+
12 rows in set (0.00 sec)
#-- sql98的标准写法
mysql> select * from student cross join grade;
+----+---------+----------+----+-----------------------+
| id | name | class_id | id | name |
+----+---------+----------+----+-----------------------+
| 3 | 张三3 | 2 | 1 | Java精品班 |
| 2 | 张三2 | 3 | 1 | Java精品班 |
| 1 | 张三 | 1 | 1 | Java精品班 |
| 3 | 张三3 | 2 | 2 | python数据分析班 |
| 2 | 张三2 | 3 | 2 | python数据分析班 |
| 1 | 张三 | 1 | 2 | python数据分析班 |
| 3 | 张三3 | 2 | 4 | 云原生高级班 |
| 2 | 张三2 | 3 | 4 | 云原生高级班 |
| 1 | 张三 | 1 | 4 | 云原生高级班 |
| 3 | 张三3 | 2 | 3 | 网络安全班 |
| 2 | 张三2 | 3 | 3 | 网络安全班 |
| 1 | 张三 | 1 | 3 | 网络安全班 |
+----+---------+----------+----+-----------------------+
12 rows in set (0.00 sec)
# 内连接
mysql> select * from student, grade where student.class_id = grade.id;
+----+---------+----------+----+-----------------------+
| id | name | class_id | id | name |
+----+---------+----------+----+-----------------------+
| 1 | 张三 | 1 | 1 | Java精品班 |
| 2 | 张三2 | 3 | 3 | 网络安全班 |
| 3 | 张三3 | 2 | 2 | python数据分析班 |
+----+---------+----------+----+-----------------------+
3 rows in set (0.00 sec)
mysql> select * from student, grade where student.class_id = grade.id and student.name = '张三';
+----+--------+----------+----+---------------+
| id | name | class_id | id | name |
+----+--------+----------+----+---------------+
| 1 | 张三 | 1 | 1 | Java精品班 |
+----+--------+----------+----+---------------+
1 row in set (0.00 sec)
# 注意:sql98的内连接方式时,如果不指定关联条件,不管怎么写,都是交叉连接
mysql> select * from student inner join grade;
+----+---------+----------+----+-----------------------+
| id | name | class_id | id | name |
+----+---------+----------+----+-----------------------+
| 3 | 张三3 | 2 | 1 | Java精品班 |
| 2 | 张三2 | 3 | 1 | Java精品班 |
| 1 | 张三 | 1 | 1 | Java精品班 |
| 3 | 张三3 | 2 | 2 | python数据分析班 |
| 2 | 张三2 | 3 | 2 | python数据分析班 |
| 1 | 张三 | 1 | 2 | python数据分析班 |
| 3 | 张三3 | 2 | 4 | 云原生高级班 |
| 2 | 张三2 | 3 | 4 | 云原生高级班 |
| 1 | 张三 | 1 | 4 | 云原生高级班 |
| 3 | 张三3 | 2 | 3 | 网络安全班 |
| 2 | 张三2 | 3 | 3 | 网络安全班 |
| 1 | 张三 | 1 | 3 | 网络安全班 |
+----+---------+----------+----+-----------------------+
12 rows in set (0.00 sec)
mysql> select * from student join grade;
+----+---------+----------+----+-----------------------+
| id | name | class_id | id | name |
+----+---------+----------+----+-----------------------+
| 3 | 张三3 | 2 | 1 | Java精品班 |
| 2 | 张三2 | 3 | 1 | Java精品班 |
| 1 | 张三 | 1 | 1 | Java精品班 |
| 3 | 张三3 | 2 | 2 | python数据分析班 |
| 2 | 张三2 | 3 | 2 | python数据分析班 |
| 1 | 张三 | 1 | 2 | python数据分析班 |
| 3 | 张三3 | 2 | 4 | 云原生高级班 |
| 2 | 张三2 | 3 | 4 | 云原生高级班 |
| 1 | 张三 | 1 | 4 | 云原生高级班 |
| 3 | 张三3 | 2 | 3 | 网络安全班 |
| 2 | 张三2 | 3 | 3 | 网络安全班 |
| 1 | 张三 | 1 | 3 | 网络安全班 |
+----+---------+----------+----+-----------------------+
12 rows in set (0.00 sec)
# 正确写法,必须写清楚关联条件
mysql> select * from student inner join grade on (student.class_id=grade.id);
+----+---------+----------+----+-----------------------+
| id | name | class_id | id | name |
+----+---------+----------+----+-----------------------+
| 1 | 张三 | 1 | 1 | Java精品班 |
| 2 | 张三2 | 3 | 3 | 网络安全班 |
| 3 | 张三3 | 2 | 2 | python数据分析班 |
+----+---------+----------+----+-----------------------+
3 rows in set (0.00 sec)
mysql> select * from student join grade on (student.class_id=grade.id) where student.name = "张三3";
+----+---------+----------+----+-----------------------+
| id | name | class_id | id | name |
+----+---------+----------+----+-----------------------+
| 3 | 张三3 | 2 | 2 | python数据分析班 |
+----+---------+----------+----+-----------------------+
1 row in set (0.00 sec)
# 内连接,只能查询出,存在关联关系的数据,如果不存在关联关系,如目前没有班级的学生,目前没有学生的班级
mysql> select * from student cross join grade on (student.class_id=grade.id) where student.name = "张三3";
+----+---------+----------+----+-----------------------+
| id | name | class_id | id | name |
+----+---------+----------+----+-----------------------+
| 3 | 张三3 | 2 | 2 | python数据分析班 |
+----+---------+----------+----+-----------------------+
1 row in set (0.00 sec)
# 如果要将这些没关联关系的数据查询出来,则需要使用外连接
mysql> select * from student left join grade on (student.class_id=grade.id);
+----+---------+----------+------+-----------------------+
| id | name | class_id | id | name |
+----+---------+----------+------+-----------------------+
| 1 | 张三 | 1 | 1 | Java精品班 |
| 2 | 张三2 | 3 | 3 | 网络安全班 |
| 3 | 张三3 | 2 | 2 | python数据分析班 |
+----+---------+----------+------+-----------------------+
3 rows in set (0.00 sec)
mysql> select * from student right join grade on (student.class_id=grade.id);
+------+---------+----------+----+-----------------------+
| id | name | class_id | id | name |
+------+---------+----------+----+-----------------------+
| 1 | 张三 | 1 | 1 | Java精品班 |
| 3 | 张三3 | 2 | 2 | python数据分析班 |
| NULL | NULL | NULL | 4 | 云原生高级班 |
| 2 | 张三2 | 3 | 3 | 网络安全班 |
+------+---------+----------+----+-----------------------+
4 rows in set (0.00 sec)
# 注意:mysql不支持全连接查询 full join
# 但是SQL存在联合查询 union 、union all
# 注意:联合查询,必须保证查询的多条SQL返回的结果 结构必须一致,所以联合查询常见于查询一张表