1. SQL语言
1.1 关系型数据库的常见组件
- 数据库:database 表的集合,物理上表现为一个目录
- 表:table,行:row 列:column
- 索引:index
- 视图:view,虚拟的表
- 存储过程:procedure
- 存储函数:function
- 触发器:trigger
- 事件调度器:event scheduler,任务计划
- 用户:user
- 权限:privilege
1.2 SQL语言语法标准
1.2.1 SQL 语言规范
- 在数据库系统中,SQL 语句不区分大小写,建议用大写
- SQL语句可单行或多行书写,默认以 " ; " 结尾
- 关键词不能跨多行或简写
- 用空格和TAB缩进来提高语句的可读性
- 子句通常位于独立行,便于编辑,提高可读性
注释:
SQL标准
#单行注释,注意有空格
-- 注释内容
#多行注释
/*注释内容
注释内容
注释内容*/
MySQL注释:
# 注释内容
1.2.2 数据库对象和命名
数据库的组件(对象):
数据库、表、索引、视图、用户、存储过程、函数、触发器、事件调度器等
命名规则:
- 必须以字母开头,后续可以包括字母,数字和三个特殊字符(# _ $)
- 不要使用MySQL的保留字
1.2.3 SQL语句分类
-
DDL: Data Defination Language 数据定义语言
CREATE,DROP,ALTER
-
DML: Data Manipulation Language 数据操纵语言
INSERT,DELETE,UPDATE
软件开发:CRUD
-
DQL:Data Query Language 数据查询语言
SELECT
-
DCL:Data Control Language 数据控制语言
GRANT,REVOKE
-
TCL:Transaction Control Language 事务控制语言
COMMIT,ROLLBACK,SAVEPOINT
1.2.4 SQL语句构成
关健字Keyword组成子句clause,多条clause组成语句
示例
SELECT * #SELECT子句
FROM products #FROM子句
WHERE price>666 #WHERE子句
说明:一组SQL语句由三个子句构成,SELECT,FROM和WHERE是关键字
获取SQL 命令使用帮助:
官方帮助:
https://dev.mysql.com/doc/refman/8.0/en/sql-statements.html
查看SQL帮助
help contents
mysql> HELP KEYWORD(关键字) 如help Data Definition
1.2.5 字符集和排序
早期MySQL版本默认为 latin1,从MySQL8.0开始默认字符集已经为 utf8mb4。
注意:
MySQL中的utf8是低配的,只支持3个字节字符,4个字节的生僻字表情包录入会乱码,真正的utf8是utf8mb4
查看支持所有字符集:
SHOW CHARACTER SET;
SHOW CHARSET;
查看当前默认字符集
show variables like 'character%';
查看支持所有排序规则:
SHOW COLLATION;#注意
utf8_general_ci不区分大小写
utf8_bin 区分大小写
查看当前使用的排序规则
SHOW VARIABLES LIKE 'collation%';
设置服务器默认的字符集,
vim /etc/my.cnf
[mysqld]
character-set-server=utf8mb4
设置mysql客户端默认的字符集
vim /etc/my.cnf
#针对mysql客户端
[mysql]
default-character-set=utf8mb4
#针对所有MySQL客户端
[client]
default-character-set=utf8
/usr/local/mysql/share/charsets/ 目录中存储的是 MySQL 数据库使用的字符集的相关定义文件
1.3 管理数据库
1.3.1 创建数据库
CREATE DATABASE|SCHEMA [IF NOT EXISTS] 'DB_NAME'
CHARACTER SET 'character set name' #指定字符集
COLLATE 'collate name'; #指定排序规则
范例:
MariaDB [(none)]> create database db1;
Query OK, 1 row affected (0.00 sec)MariaDB [(none)]> show create database db1; #显示数据库 db1 的创建语句,包括该数据库的字符集、排序规则等元数据。
+----------+----------------------------------------------------------------+
| Database | Create Database |
+----------+----------------------------------------------------------------+
| db1 | CREATE DATABASE `db1` /*!40100 DEFAULT CHARACTER SET latin1 */ |
+----------+----------------------------------------------------------------+
1 row in set (0.00 sec)#db.opt存储了与特定数据库相关的选项和参数设置
[root@Centos7 ~]#cat /var/lib/mysql/db1/db.opt
default-character-set=latin1
default-collation=latin1_swedish_ci#创建数据库提示已存在
MariaDB [(none)]> create database db1;
ERROR 1007 (HY000): Can't create database 'db1'; database exists#IF NOT EXISTS:如果数据库db1不存在,则创建一个名为db1的数据库。如果该数据库已经存在,则不会发生任何更改,并且会返回一条警告信息。
MariaDB [(none)]> create database IF NOT EXISTS db1;
Query OK, 1 row affected, 1 warning (0.00 sec)#查看告警信息
MariaDB [(none)]> show warnings;
+-------+------+----------------------------------------------+
| Level | Code | Message |
+-------+------+----------------------------------------------+
| Note | 1007 | Can't create database 'db1'; database exists |
+-------+------+----------------------------------------------+
1 row in set (0.00 sec)
范例:指定字符集创建新数据库
MariaDB [(none)]> create database IF NOT EXISTS db2 CHARACTER SET 'utf8';
Query OK, 1 row affected (0.00 sec)MariaDB [(none)]> show create database db2;
+----------+--------------------------------------------------------------+
| Database | Create Database |
+----------+--------------------------------------------------------------+
| db2 | CREATE DATABASE `db2` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+----------+--------------------------------------------------------------+
1 row in set (0.00 sec)#可以用以下简写
MariaDB [(none)]> create database test charset=utf8;
Query OK, 1 row affected (0.00 sec)MariaDB [(none)]> show create database test;
+----------+---------------------------------------------------------------+
| Database | Create Database |
+----------+---------------------------------------------------------------+
| test | CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+----------+---------------------------------------------------------------+
1 row in set (0.00 sec)
范例: 手动创建数据库
MariaDB [(none)]> create database zabbix character set utf8 collate utf8_bin;
Query OK, 1 row affected (0.00 sec)MariaDB [(none)]> show create database zabbix;
+----------+----------------------------------------------------------------------------------+
| Database | Create Database |
+----------+----------------------------------------------------------------------------------+
| zabbix | CREATE DATABASE `zabbix` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_bin */ |
+----------+----------------------------------------------------------------------------------+
1 row in set (0.00 sec)
1.3.2 修改数据库
ALTER DATABASE DB_NAME character set utf8;
范例:
MariaDB [(none)]> alter database db1 character set utf8 collate utf8_bin;
Query OK, 1 row affected (0.00 sec)MariaDB [(none)]> show create database db1;
+----------+-------------------------------------------------------------------------------+
| Database | Create Database |
+----------+-------------------------------------------------------------------------------+
| db1 | CREATE DATABASE `db1` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_bin */ |
+----------+-------------------------------------------------------------------------------+
1 row in set (0.00 sec)
1.3.3 删除数据库
DROP DATABASE|SCHEMA [IF EXISTS] 'DB_NAME';
MariaDB [(none)]> drop database db1;
Query OK, 0 rows affected (0.00 sec)MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db2 |
| mysql |
| performance_schema |
| test |
| zabbix |
+--------------------+
6 rows in set (0.00 sec)[root@Centos7 ~]#ls /var/lib/mysql/ #删库后目录不存在
aria_log.00000001 db2 ib_logfile0 mysql performance_schema zabbix
aria_log_control ibdata1 ib_logfile1 mysql.sock test
1.3.4 查看数据库列表
SHOW DATABASES;
范例:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.01 sec)
1.4 数据类型
数据类型:
- 数据长什么样
- 数据需要多少空间来存放
数据类型
- 系统内置数据类型
- 用户定义数据类型
MySQL支持多种内置数据类型
- 数值类型
- 日期/时间类型
- 字符串(字符)类型
数据类型参考链接
https://dev.mysql.com/doc/refman/8.0/en/data-types.html
选择正确的数据类型对于获得高性能至关重要,三大原则:
- 更小的通常更好,尽量使用可正确存储数据的最小数据类型
- 简单就好,简单数据类型的操作通常需要更少的CPU周期
- 尽量避免NULL,包含为NULL的列,对MySQL更难优化
1.4.1整数型
tinyint(m) 1个字节 范围(-128~127)
smallint(m) 2个字节 范围(-32768~32767)
mediumint(m) 3个字节 范围(-8388608~8388607)
int(m) 4个字节 范围(-2147483648~2147483647)
bigint(m) 8个字节 范围(+-9.22*10的18次方)
上述数据类型,如果加修饰符unsigned后,则最大值翻倍,(默认最高位为负号位,使用unsigned没有最高负号位,则最大值翻倍)。
如:tinyint unsigned的取值范围为(0~255)
int(m)里的m是表示SELECT查询结果集中的显示宽度,并不影响实际的取值范围,规定了MySQL的一些 交互工具(例如MySQL命令行客户端)用来显示字符的个数。对于存储和计算来说,Int(1)和Int(20)是 相同的
BOOL,BOOLEAN:布尔型,是TINYINT(1)的同义词。zero值被视为假,非zero值视为真
范例:int(m)
#在查询时使用该列时,在交互工具中可能将其截断设为最大指定宽度
CREATE TABLE person (id INT, name VARCHAR(50),age INT(1));INSERT INTO person (id, name, age) VALUES (1, 'John', 25);SELECT age FROM person;
+-----+
| age |
+-----+
| 2 |
+-----+
1.4.2 浮点型(float和double),近似值
float(m,d) 单精度浮点型 8位精度(4字节) m总个数,d小数位, 注意: 小数点不占用总个数
double(m,d) 双精度浮点型16位精度(8字节) m总个数,d小数位, 注意: 小数点不占用总个数
示例:
设一个字段定义为float(6,3),如果插入一个数123.45678,实际数据库里存的是123.457,但总个数还以实际为准,即6位
1.4.3 定点数
在数据库中存放的是精确值,存为十进制
格式 decimal(m,d) 表示 最多 m 位数字,其中 d 个小数,小数点不算在长度内
比如: DECIMAL(6,2) 总共能存6位数字,末尾2位是小数,字段最大值 9999.99 (小数点不算在长度内)
参数m<65 是总个数,d<30且 d<m 是小数位
MySQL5.0和更高版本将数字打包保存到一个二进制字符串中(每4个字节存9个数字)。
例如: decimal(18,9)小数点两边将各存储9个数字,一共使用9个字节:其中,小数点前的9个数字用4个字节,小数点后的9个数字用4个字节,小数点本身占1个字节
浮点类型在存储同样范围的值时,通常比decimal使用更少的空间。float使用4个字节存储。double占用8个字节
因为需要额外的空间和计算开销,所以应该尽量只在对小数进行精确计算时才使用decimal,例如存储
财务数据。但在数据量比较大的时候,可以考虑使用bigint代替decimal
1.4.4 字符串(char,varchar,text)
char(n) 固定长度,最多255个字符,注意不是字节
varchar(n) 可变长度,最多65535个字符
tinytext 可变长度,最多255个字符
text 可变长度,最多65535个字符
mediumtext 可变长度,最多2的24次方-1个字符
longtext 可变长度,最多2的32次方-1个字符
BINARY(M) 固定长度,可存二进制或字符,长度为0-M字节
VARBINARY(M) 可变长度,可存二进制或字符,允许长度为0-M字节
内建类型:ENUM枚举, SET集合
char和varchar的比较:
参考:https://dev.mysql.com/doc/refman/8.0/en/char.html
Value | CHAR(4) | Storage Required | VARCHAR(4) | Storage Required |
---|---|---|---|---|
'' | ' ' | 4 bytes | '' | 1 byte |
'ab' | 'ab ' | 4 bytes | 'ab' | 3 bytes |
'abcd' | 'abcd' | 4 bytes | 'abcd' | 5 bytes |
'abcdefgh' | 'abcd' | 4 bytes | 'abcd' | 5 bytes |
1.char(n) 若存入字符数小于n,则以空格补于其后,查询之时再将空格去掉,所以char类型存储的字符串末尾不能有空格,varchar不限于此
2.char(n) 固定长度,char(4)不管是存入几个字符,都将占用4个字节,varchar是存入的实际字符数+1个字节(n< n>255),所以varchar(4),存入3个字符将占用4个字节
3.char类型的字符串检索速度要比varchar类型的快
varchar 和 text:
1.varchar可指定n,text不能指定,内部存储varchar是存入的实际字符数+1个字节(n< n>255),text是实际字符数+2个字节。
2.text类型不能有默认值
3.varchar可直接创建索引,text创建索引要指定前多少个字符。varchar查询速度快于text
面试题: VARCHAR(50) 能存放几个 UTF8 编码的汉字?
存放的汉字个数与版本相关。
mysql4.0以下版本,varchar(50) 指的是50字节,如果存放UTF8格式编码的汉字时(每个汉字3字节),只能存放16个。
mysql5.0以上版本,varchar(50) 指的是50字符,无论存放的是数字、字母还是UTF8编码的汉字,都可以存放50个。
1.4.5 二进制数据BLOB
BLOB和text存储方式不同,TEXT以文本方式存储,英文存储区分大小写,而Blob以二进制方式存储,不分大小写
BLOB存储的数据只能整体读出
TEXT可以指定字符集,BLOB不用指定字符集
1.4.6 日期时间类型
date 日期 '2008-12-2'
time 时间 '12:25:36'
datetime 日期时间 '2008-12-2 22:06:44'
timestamp 自动存储记录修改时间
YEAR(2), YEAR(4):年份
timestamp 此字段里的时间数据会随其他字段修改的时候自动刷新,这个数据类型的字段可以存放这条记录最后被修改的时间
1.4.7 修饰符
适用所有类型的修饰符:
NULL 数据列可包含NULL值,默认值
NOT NULL 数据列不允许包含NULL值,相当于网站注册表中的 * 为必填选项
DEFAULT 默认值
PRIMARY KEY 主键,所有记录中此字段的值不能重复,且不能为NULL
UNIQUE KEY 唯一键,所有记录中此字段的值不能重复,但可以为NULL
CHARACTER SET name 指定一个字符集
适用数值型的修饰符:
AUTO_INCREMENT 自动递增,适用于整数类型, 必须作用于某个key 的字段,比如primary key
UNSIGNED 无符号
范例:关于AUTO_INCREMENT
MariaDB [(none)]> SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
+--------------------------+-------+
2 rows in set (0.01 sec)# auto_increment_offset 定义初始值
# auto_increment_increment 定义步进
范例:
#创建test数据库并进入
mysql> create database test;
Query OK, 1 row affected (0.00 sec)mysql> use test
Database changed#创建t1表,字段名为id,用int类型无负数自动递增并设置为主键,设置id的初始递增值是4294967294。
mysql> create table t1(id int unsigned auto_increment primary key) auto_increment = 4294967294;
Query OK, 0 rows affected (0.03 sec)#查看t1表的详细信息
mysql> show table status from test like "t1"\G
*************************** 1. row ***************************Name: t1 Engine: InnoDB Version: 10 Row_format: Dynamic Rows: 0 Avg_row_length: 0 Data_length: 16384
Max_data_length: 0 Index_length: 0 Data_free: 0Auto_increment: 4294967294Create_time: 2023-08-08 10:43:41Update_time: NULLCheck_time: NULLCollation: utf8mb4_0900_ai_ciChecksum: NULLCreate_options: Comment:
1 row in set (0.00 sec)#因为id列为主键并设置为自动增长,插入null后会自动插入自动递增值
mysql> insert into t1 values(null);
Query OK, 1 row affected (0.00 sec)mysql> select * from t1;
+------------+
| id |
+------------+
| 4294967294 |
+------------+
1 row in set (0.00 sec)#再次插入数据
mysql> insert into t1 values(null);
Query OK, 1 row affected (0.01 sec)mysql> select * from t1;
+------------+
| id |
+------------+
| 4294967294 |
| 4294967295 |
+------------+
2 rows in set (0.00 sec)#再次插入报错,因为INT UNSIGNED类型的列最大可存储的值是4294967295。
mysql> insert into t1 values(null);
ERROR 1062 (23000): Duplicate entry '4294967295' for key 't1.PRIMARY'MariaDB [test]> insert into t1 values(null);
ERROR 167 (22003): Out of range value for column 'id' at row 1#修改id列数据类型为bigint,测试插入成功
MariaDB [test]> alter table t1 modify id bigint auto_increment ;
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0MariaDB [test]> desc t1;
+-------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
+-------+------------+------+-----+---------+----------------+
1 row in set (0.01 sec)MariaDB [test]> insert into t1 values(null);
Query OK, 1 row affected (0.00 sec)MariaDB [test]> select * from t1;
+------------+
| id |
+------------+
| 4294967294 |
| 4294967295 |
| 4294967296 |
+------------+
3 rows in set (0.00 sec)
1.5 DDL 语句
表:二维关系
设计表:遵循规范
定义:字段,索引
- 字段:字段名,字段数据类型,修饰符
- 约束,索引:应该创建在经常用作查询条件的字段上
1.5.1 创建表
参考文档:
https://dev.mysql.com/doc/refman/8.0/en/create-table.html
创建表:
CREATE TABLE
获取帮助:
HELP CREATE TABLE
外键管理参考文档
https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html
创建表的方法
(1) 直接创建
CREATE TABLE [IF NOT EXISTS] 'tbl_name' (col1 type1 修饰符, col2 type2 修饰符, ...)
#字段信息
col type1 #列名 类型
PRIMARY KEY(col1,...)
INDEX(col1, ...)
UNIQUE KEY(col1, ...)
#表选项:
ENGINE [=] engine_name
ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}
注意:
- Storage Engine是指表类型,也即在表创建时指明其使用的存储引擎
- 同一库中不同表可以使用不同的存储引擎
- 同一个库中表建议要使用同一种存储引擎类型
范例:创建表
MariaDB [test]> create table student(id int unsigned auto_increment primary key,name varchar(20) not null,age tinyint unsigned,gender enum('M','F') default 'M')ENGINE=InnoDB auto_increment=10 default charset=utf8;
Query OK, 0 rows affected (0.01 sec)
#id字段以10初始值#desc查看表结构
MariaDB [test]> desc student;
+--------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| age | tinyint(3) unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
+--------+---------------------+------+-----+---------+----------------+
4 rows in set (0.01 sec)#插入数据并查看
MariaDB [test]> insert student (name,age) values('xiaoming',20);
Query OK, 1 row affected (0.00 sec)MariaDB [test]> select * from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 10 | xiaoming | 20 | M |
+----+----------+------+--------+
1 row in set (0.00 sec)MariaDB [test]> insert student (name,age,gender) values('xiaohong',18,'f');
Query OK, 1 row affected (0.00 sec)MariaDB [test]> select * from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
+----+----------+------+--------+
2 rows in set (0.00 sec)#创建表并将id和name字段设置为复合主键
CREATE TABLE employee (id int UNSIGNED NOT NULL,name VARCHAR(20) NOT NULL,age tinyint UNSIGNED,PRIMARY KEY(id,name));
范例:auto_increment 属性
#查看自动递增属性
MariaDB [(none)]> show variables like 'auto_inc%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
+--------------------------+-------+
2 rows in set (0.00 sec)#设置步进为10,初始值为3
MariaDB [(none)]> SET @@auto_increment_increment=10;
Query OK, 0 rows affected (0.00 sec)MariaDB [(none)]> set @@auto_increment_offset=3;
Query OK, 0 rows affected (0.00 sec)MariaDB [(none)]> show variables like 'auto_inc%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 10 |
| auto_increment_offset | 3 |
+--------------------------+-------+
2 rows in set (0.00 sec)#创建autoinc1表,插入4条数据并查看
MariaDB [hellodb]> CREATE TABLE autoinc1 (col INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
Query OK, 0 rows affected (0.004 sec)MariaDB [hellodb]> INSERT INTO autoinc1 VALUES (null),(null),(null),(null);
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0MariaDB [hellodb]> SELECT col FROM autoinc1;
+-----+
| col |
+-----+
| 3 |
| 13 |
| 23 |
| 33 |
+-----+
4 rows in set (0.00 sec)
范例:时间类型
#当前时间戳(CURRENT_TIMESTAMP),并且不能为空(NOT NULL)。
MariaDB [hellodb]> create table testdate (id int auto_increment primary key,date timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL);
MariaDB [hellodb]> insert testdate ()values(),(),();
MariaDB [hellodb]> select * from testdate;
+----+---------------------+
| id | date |
+----+---------------------+
| 1 | 2023-08-08 05:03:51 |
| 2 | 2023-08-08 05:03:51 |
| 3 | 2023-08-08 05:03:51 |
+----+---------------------+
3 rows in set (0.00 sec)
(2) 通过查询现存表创建;新表会被直接插入查询而来的数据
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)]
[table_options]
[partition_options] select_statement
范例:
MariaDB [hellodb]> create database db1;
Query OK, 1 row affected (0.00 sec)MariaDB [hellodb]> use db1
Database changed#通过查询mysql库user表中的user,host,password字段,创建db1库的表user
MariaDB [db1]> create table user select user,host,password from mysql.user;
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0MariaDB [db1]> show tables;
+---------------+
| Tables_in_db1 |
+---------------+
| user |
+---------------+
1 row in set (0.00 sec)MariaDB [db1]> desc user;
+----------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+----------+------+-----+---------+-------+
| user | char(16) | NO | | | |
| host | char(60) | NO | | | |
| password | char(41) | NO | | | |
+----------+----------+------+-----+---------+-------+
3 rows in set (0.00 sec)MariaDB [db1]> select * from user;
+------+-----------+----------+
| user | host | password |
+------+-----------+----------+
| root | localhost | |
| root | 127.0.0.1 | |
| root | ::1 | |
+------+-----------+----------+
3 rows in set (0.00 sec)
(3) 通过复制现存的表的表结构创建,但不复制数据
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name { LIKE old_tbl_name | (LIKE old_tbl_name) }
范例:
MariaDB [hellodb]> desc students;
+-----------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+----------------+
| StuID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| Name | varchar(50) | NO | | NULL | |
| Age | tinyint(3) unsigned | NO | | NULL | |
| Gender | enum('F','M') | NO | | NULL | |
| ClassID | tinyint(3) unsigned | YES | | NULL | |
| TeacherID | int(10) unsigned | YES | | NULL | |
+-----------+---------------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)MariaDB [hellodb]> create table teacher like students;
Query OK, 0 rows affected (0.00 sec)MariaDB [hellodb]> desc teacher;
+-----------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+----------------+
| StuID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| Name | varchar(50) | NO | | NULL | |
| Age | tinyint(3) unsigned | NO | | NULL | |
| Gender | enum('F','M') | NO | | NULL | |
| ClassID | tinyint(3) unsigned | YES | | NULL | |
| TeacherID | int(10) unsigned | YES | | NULL | |
+-----------+---------------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
范例: 创建外键表
mysql> create table school (id int primary key auto_increment,name varchar(10));
Query OK, 0 rows affected (0.03 sec)#foreign key(school_id) references school(id)定义了外键约束。它指示该表中的 school_id列是与另一个名为school表中的主键列id相关联的外部引用。
mysql> create table teacher(id int primary key auto_increment,name varchar(10),school_id int,foreign key(school_id) references school(id));
Query OK, 0 rows affected (0.02 sec)mysql> desc school;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(10) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)mysql> desc teacher;
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(10) | YES | | NULL | |
| school_id | int | YES | MUL | NULL | |
+-----------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)mysql> mysql> show create table teacher;
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| teacher | CREATE TABLE `teacher` (`id` int NOT NULL AUTO_INCREMENT,`name` varchar(10) DEFAULT NULL,`school_id` int DEFAULT NULL,PRIMARY KEY (`id`),KEY `school_id` (`school_id`), #表示在当前表中创建了一个名为 school_id 的索引。索引可以提高查询性能和数据检索速度CONSTRAINT `teacher_ibfk_1` FOREIGN KEY (`school_id`) REFERENCES `school` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)CONSTRAINT 'teacher_ibfk_1' FOREIGN KEY ('school_id') REFERENCES 'school' ('id'): 这表示在当前表中创建了一个名为 teacher_ibfk_1 的外键约束。它将列 school_id 作为外键,并将其关联到另一个表 school 的主键列 id 上。
外键 (FOREIGN KEY) 是用来建立两个相关表之间关系的机制。
'teacher_ibfk_1' 是该外键约束的名称,你可以根据需要自定义名称。
'school_id' 是当前表中被指定为外键的列名。
'REFERENCES school (id)' 表示参照(引用)了另一张名为 'school' 的表,并使用其主键列 'id'.mysql> insert school values(0,'magedu'),(0,'wangedu');mysql> select * from school;
+----+--------+
| id | name |
+----+--------+
| 1 | magedu |
| 2 | magedu |
2 rows in set (0.00 sec)mysql> insert teacher values(0,'xiaoming',1);
mysql> insert teacher values(0,'xiaohong',2);
Query OK, 1 row affected (0.00 sec)mysql> select * from teacher;
+----+----------+-----------+
| id | name | school_id |
+----+----------+-----------+
| 1 | xiaoming | 1 |
| 2 | xiaohong | 2 |
+----+----------+-----------+
2 rows in set (0.00 sec)#无法添加或更新子行: 外键约束失败。test库teacher表,外键约束名teacher_ibfk_1,外键列school_id引用了school表的id列
mysql> insert teacher values(0,'xiaobai',3);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`teacher`, CONSTRAINT `teacher_ibfk_1` FOREIGN KEY (`school_id`) REFERENCES `school` (`id`))
范例: 生产表结构
范例: 生产表
1.5.2 表查看
查看表:
SHOW TABLES [FROM db_name]
查看表创建命令:
SHOW CREATE TABLE tbl_name
查看表结构:
DESC [db_name.]tb_name
SHOW COLUMNS FROM [db_name.]tb_name
查看表状态:
SHOW TABLE STATUS LIKE 'tbl_name'
查看支持的engine类型
SHOW ENGINES;
范例:查看表
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| school |
| t1 |
| teacher |
+----------------+
3 rows in set (0.00 sec)
范例:查看表结构,下面命令执行效果一样
mysql> desc school;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(10) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)mysql> show columns from school;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(10) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
范例:查看表创建
mysql> show create table school;
+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| school | CREATE TABLE `school` (`id` int NOT NULL AUTO_INCREMENT,`name` varchar(10) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
范例:查看表状态
mysql> show table status like 'school'\G
*************************** 1. row ***************************Name: schoolEngine: InnoDBVersion: 10Row_format: DynamicRows: 6Avg_row_length: 2730Data_length: 16384
Max_data_length: 0Index_length: 0Data_free: 0Auto_increment: 12Create_time: 2023-08-08 17:38:52Update_time: 2023-08-08 20:56:33Check_time: NULLCollation: utf8mb4_0900_ai_ciChecksum: NULLCreate_options: Comment:
1 row in set (0.01 sec)
查看库中所有表状态
SHOW TABLE STATUS FROM db_name
范例:
mysql> show table status from test\G
*************************** 1. row ***************************Name: schoolEngine: InnoDBVersion: 10Row_format: DynamicRows: 6Avg_row_length: 2730Data_length: 16384
Max_data_length: 0Index_length: 0Data_free: 0Auto_increment: 12Create_time: 2023-08-08 17:38:52Update_time: 2023-08-08 20:56:33Check_time: NULLCollation: utf8mb4_0900_ai_ciChecksum: NULLCreate_options: Comment:
*************************** 2. row ***************************Name: t1Engine: InnoDBVersion: 10Row_format: DynamicRows: 0Avg_row_length: 0Data_length: 16384
Max_data_length: 0Index_length: 0Data_free: 0Auto_increment: 4294967294Create_time: 2023-08-08 14:38:54Update_time: NULLCheck_time: NULLCollation: utf8mb4_0900_ai_ciChecksum: NULLCreate_options: Comment:
*************************** 3. row ***************************Name: teacherEngine: InnoDBVersion: 10Row_format: DynamicRows: 2Avg_row_length: 8192Data_length: 16384
Max_data_length: 0Index_length: 16384Data_free: 0Auto_increment: 4Create_time: 2023-08-08 17:41:34Update_time: 2023-08-08 20:53:01Check_time: NULLCollation: utf8mb4_0900_ai_ciChecksum: NULLCreate_options: Comment:
3 rows in set (0.01 sec)
1.5.3 修改和删除表
修改表
ALTER TABLE 'tbl_name'
#字段:
#添加字段:add 可选:FIRST,将新列插到所有列之前,AFTER col_name,将新列插到已存在的某个特定列之后
ADD col1 data_type [FIRST|AFTER col_name]
#删除字段:drop
#修改字段:
alter(默认值), change(字段名), modify(字段属性)
查看修改表帮助
Help ALTER TABLE
删除表
DROP TABLE [IF EXISTS] 'tbl_name';
修改表范例
#修改表名
ALTER TABLE students RENAME s1;#添加字段
ALTER TABLE s1 ADD phone varchar(11) AFTER name;#修改字段类型
ALTER TABLE s1 MODIFY phone int;#修改字段名称和类型
ALTER TABLE s1 CHANGE COLUMN phone mobile char(11);#删除字段
ALTER TABLE s1 DROP COLUMN mobile;#修改字符集
ALTER TABLE s1 character set utf8;#修改字段名数据类型和字符集
ALTER TABLE s1 change name name1 varchar(20) character set utf8;#添加字段
ALTER TABLE students ADD gender ENUM('m','f');#修改is_del列数据类型为bool布尔值,默认是false
alter table student modify is_del bool default false;#修改字段名和类型:id列修改为sid指定数据类型
ALETR TABLE students CHANGE id sid int UNSIGNED NOT NULL PRIMARY KEY;#删除字段
ALTER TABLE students DROP age;#查看表结构
DESC students;#新建表无主键,添加和删除主键
CREATE TABLE t1 SELECT * FROM students;
ALTER TABLE t1 add primary key (stuid);
ALTER TABLE t1 drop primary key ;#添加外键
ALTER TABLE students add foreign key(TeacherID) references teachers(tid);#删除外键
SHOW CREATE TABLE students #查看外键名
ALTER TABLE students drop foreign key <外键名>;
1.6 DML 语句
1.61 INSERT 语句
功能:一次插入一行或多行数据
语 法
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE][INTO] tbl_name [(col_name,...)]{VALUES | VALUE} ({expr | DEFAULT},...),(...),...[ ON DUPLICATE KEY UPDATE #如果重复更新之col_name=expr[, col_name=expr] ... ]INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE][INTO] tbl_nameSET col_name={expr | DEFAULT}, ...[ ON DUPLICATE KEY UPDATEcol_name=expr[, col_name=expr] ... ]INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE][INTO] tbl_name [(col_name,...)]SELECT ...[ ON DUPLICATE KEY UPDATEcol_name=expr[, col_name=expr] ... ]
简化写法:
INSERT tbl_name [(col1,...)] VALUES (val1,...), (val21,...)
范例: 全值插入
mysql> insert student values(0,'wang',18,default);
Query OK, 1 row affected (0.00 sec)mysql> select * from student;
+----+------+------+--------+
| id | name | age | gender |
+----+------+------+--------+
| 1 | wang | 18 | M |
+----+------+------+--------+
1 row in set (0.00 sec)
范例: 部分列插入
mysql> insert student(name,age)values('zhang',20);
Query OK, 1 row affected (0.00 sec)mysql> insert student(id,name,age)values(default,'li',19);
Query OK, 1 row affected (0.00 sec)mysql> insert student(id,name,gender)values(null,'zhao','F');
Query OK, 1 row affected (0.01 sec)mysql> select * from student;
+----+-------+------+--------+
| id | name | age | gender |
+----+-------+------+--------+
| 1 | wang | 18 | M |
| 2 | zhang | 20 | M |
| 3 | li | 19 | M |
| 4 | zhao | NULL | F |
+----+-------+------+--------+
4 rows in set (0.00 sec)
1.6.2 UPDATE 语句
语法:
UPDATE [LOW_PRIORITY] [IGNORE] table_referenceSET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...[WHERE where_condition][ORDER BY ...][LIMIT row_count]
注意:一定要有限制条件,否则将修改所有行的指定字段
可利用mysql 选项避免此错误:
mysql -U | --safe-updates| --i-am-a-dummy[root@centos8 ~]#vim /etc/my.cnf
[mysql]
safe-updates
范例:
mysql> select * from teachers;
+----+----------+-----------+
| id | name | school_id |
+----+----------+-----------+
| 1 | xiaoming | 3 |
| 27 | xiaomig | 13 |
+----+----------+-----------+
2 rows in set (0.00 sec)mysql> update teachers set id=2 where name='xiaomig';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0mysql> select * from teachers;
+----+----------+-----------+
| id | name | school_id |
+----+----------+-----------+
| 1 | xiaoming | 3 |
| 2 | xiaomig | 13 |
+----+----------+-----------+
2 rows in set (0.00 sec)
1.6.3 DELETE 语句
删除表中数据,但不会自动缩减数据文件的大小。
语法:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name[WHERE where_condition][ORDER BY ...][LIMIT row_count]
#可先排序再指定删除的行数
范例:
mysql> select * from student;
+----+-------+------+--------+--------+
| id | name | age | gender | is_del |
+----+-------+------+--------+--------+
| 1 | wang | 18 | M | 0 |
| 2 | zhang | 20 | M | 0 |
| 4 | zhao | NULL | F | 1 |
+----+-------+------+--------+--------+
3 rows in set (0.00 sec)#未指定限制条件清空表中所有数据,慎用!
mysql> delete from student;
Query OK, 3 rows affected (0.01 sec)mysql> select * from student;
Empty set (0.01 sec)#指定条件删除
mysql> select * from student;
+----+------+------+--------+--------+
| id | name | age | gender | is_del |
+----+------+------+--------+--------+
| 3 | zhao | NULL | F | 0 |
| 4 | li | NULL | F | 0 |
+----+------+------+--------+--------+
2 rows in set (0.00 sec)mysql> delete from student where id=4;
Query OK, 1 row affected (0.00 sec)mysql> select * from student;
+----+------+------+--------+--------+
| id | name | age | gender | is_del |
+----+------+------+--------+--------+
| 3 | zhao | NULL | F | 0 |
+----+------+------+--------+--------+
1 row in set (0.00 sec)
注意:一定要有限制条件,否则将清空表中的所有数据
如果想清空表,保留表结构,也可以使用下面语句,此语句会自动缩减数据文件的大小。
TRUNCATE TABLE tbl_name;
缩减表大小
OPTIMIZE TABLE tb_name
范例: 删除数据可以使用逻辑删除,添加一个标识字段实现,删除数据即修改标识字段
mysql> alter table student add is_del bool default false;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0mysql> desc student;
+--------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(10) | YES | | NULL | |
| age | int | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
| is_del | tinyint(1) | YES | | 0 | |
+--------+---------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)#is_del列的布尔值是0表示未被逻辑上删除,1或非零值表示已经被逻辑删除。
mysql> select * from student;
+----+-------+------+--------+--------+
| id | name | age | gender | is_del |
+----+-------+------+--------+--------+
| 1 | wang | 18 | M | 0 |
| 2 | zhang | 20 | M | 0 |
| 4 | zhao | NULL | F | 1 |
+----+-------+------+--------+--------+
3 rows in set (0.00 sec)#查看未被逻辑删除的数据
mysql> select * from student where is_del=0;
+----+-------+------+--------+--------+
| id | name | age | gender | is_del |
+----+-------+------+--------+--------+
| 1 | wang | 18 | M | 0 |
| 2 | zhang | 20 | M | 0 |
+----+-------+------+--------+--------+
2 rows in set (0.00 sec)
1.7 DQL 语句
1.7.1 单表操作
语法:
SELECT[ALL | DISTINCT | DISTINCTROW ][SQL_CACHE | SQL_NO_CACHE]select_expr [, select_expr ...][FROM table_references[WHERE where_condition][GROUP BY {col_name | expr | position}[ASC | DESC], ... [WITH ROLLUP]][HAVING where_condition][ORDER BY {col_name | expr | position}[ASC | DESC], ...][LIMIT {[offset,] row_count | row_count OFFSET offset}][FOR UPDATE | LOCK IN SHARE MODE]
说明:
-
字段显示可以使用别名:
col1 AS alias1, col2 AS alias2, ...
-
WHERE子句:指明过滤条件以实现"选择"的功能:
过滤条件:布尔型表达式
算术操作符:+, -, *, /, %
比较操作符:=,<=>(相等或都为空), <>, !=(非标准SQL), >, >=, <, <=
范围查询: BETWEEN min_num AND max_num
不连续的查询: IN (element1, element2, ...)
空查询: IS NULL, IS NOT NULL
DISTINCT 去除重复行,范例:SELECT DISTINCT gender FROM students;
模糊查询: LIKE 使用 % 表示任意长度的任意字符 _ 表示任意单个字符
RLIKE:正则表达式,索引失效,不建议使用
REGEXP:匹配字符串可用正则表达式书写模式,同上
逻辑操作符:NOT,AND,OR,XOR
-
GROUP BY:根据指定的条件把查询结果进行"分组"以用于做"聚合"运算
常见聚合函数: count(), sum(), max(), min(), avg(),注意:聚合函数不对null统计
HAVING: 对分组聚合运算后的结果指定过滤条件
一旦分组 group by ,select语句后只跟分组的字段,聚合函数
-
ORDER BY: 根据指定的字段对查询结果进行排序
升序:ASC
降序:DESC
-
LIMIT [[offset,]row_count]:对查询的结果进行输出行数数量限制,跳过offset,显示row_count行,offset默为值为0
-
对查询结果中的数据请求施加"锁"
FOR UPDATE: 写锁,独占或排它锁,只有一个读和写操作
LOCK IN SHARE MODE: 读锁,共享锁,同时多个读操作
范例:
#PASSWORD()函数是MySQL内置的密码哈希函数,将提供的字符串加密处理,返回加密后的值。这种加密方式通常用于存储和验证用户密码。
MariaDB [hellodb]> select password("helo world");
+-------------------------------------------+
| password("helo world") |
+-------------------------------------------+
| *E3BC9AF3AC72A9C40D74D75BC9F4C9C0B7E45942 |
+-------------------------------------------+
1 row in set (0.00 sec)#md5()函数是计算给定字符串的MD5哈希值
MariaDB [hellodb]> select md5("helo world");
+----------------------------------+
| md5("helo world") |
+----------------------------------+
| 27eac27d138eaf911f054026e14f7500 |
+----------------------------------+
1 row in set (0.00 sec)
范例:字段别名
MariaDB [hellodb]> select stuid 学员ID,name 姓名,gender 性别 from students;
+----------+---------------+--------+
| 学员ID | 姓名 | 性别 |
+----------+---------------+--------+
| 1 | Shi Zhongyu | M |
| 2 | Shi Potian | M |
| 3 | Xie Yanke | M |
| 4 | Ding Dian | M |
| 5 | Yu Yutong | M |
| 6 | Shi Qing | M |
| 7 | Xi Ren | F |
| 8 | Lin Daiyu | F |
| 9 | Ren Yingying | F |
| 10 | Yue Lingshan | F |
| 11 | Yuan Chengzhi | M |
| 12 | Wen Qingqing | F |
| 13 | Tian Boguang | M |
| 14 | Lu Wushuang | F |
| 15 | Duan Yu | M |
| 16 | Xu Zhu | M |
| 17 | Lin Chong | M |
| 18 | Hua Rong | M |
| 19 | Xue Baochai | F |
| 20 | Diao Chan | F |
| 21 | Huang Yueying | F |
| 22 | Xiao Qiao | F |
| 23 | Ma Chao | M |
| 24 | Xu Xian | M |
| 25 | Sun Dasheng | M |
+----------+---------------+--------+
25 rows in set (0.00 sec)
范例:简单查询
mysql> desc student;
+--------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(10) | YES | | NULL | |
| gender | enum('m','f') | YES | | NULL | |
+--------+---------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)mysql> INSERT INTO student VALUES(1,'tom','m'),(2,'alice','f');
mysql> INSERT INTO student(id,name) VALUES(3,'jack'),(4,'allen');mysql> select * from student;
+----+-------+--------+
| id | name | gender |
+----+-------+--------+
| 1 | tom | m |
| 2 | alice | f |
| 3 | jack | NULL |
| 4 | allen | NULL |
+----+-------+--------+
4 rows in set (0.00 sec)#过滤出id>3d的结果
mysql> select * from student where id < 3;
+----+-------+--------+
| id | name | gender |
+----+-------+--------+
| 1 | tom | m |
| 2 | alice | f |
+----+-------+--------+
2 rows in set (0.00 sec)#过滤出gender性别是m男的结果
mysql> select * from student where gender='m';
+----+------+--------+
| id | name | gender |
+----+------+--------+
| 1 | tom | m |
+----+------+--------+
1 row in set (0.00 sec)#过滤出gender为空值的结果
mysql> select * from student where gender is null;
+----+-------+--------+
| id | name | gender |
+----+-------+--------+
| 3 | jack | NULL |
| 4 | allen | NULL |
+----+-------+--------+
2 rows in set (0.00 sec)#过滤出gender不为空值的结果
mysql> select * from student where gender is not null;
+----+-------+--------+
| id | name | gender |
+----+-------+--------+
| 1 | tom | m |
| 2 | alice | f |
+----+-------+--------+
2 rows in set (0.00 sec)#根据姓名进行降序排序并显示前2行
mysql> select * from student order by name desc limit 2;
+----+------+--------+
| id | name | gender |
+----+------+--------+
| 1 | tom | m |
| 3 | jack | NULL |
+----+------+--------+
2 rows in set (0.01 sec)#根据姓名进行降序排序并跳过第一行,显示两行(第2,3行)
mysql> select * from student order by name desc limit 1,2;
+----+-------+--------+
| id | name | gender |
+----+-------+--------+
| 3 | jack | NULL |
| 4 | allen | NULL |
+----+-------+--------+
2 rows in set (0.00 sec)#过滤出id大于等于2并且小于等于4的行
mysql> select * from student where id >=2 and id<=4;
+----+-------+--------+
| id | name | gender |
+----+-------+--------+
| 2 | alice | f |
| 3 | jack | NULL |
| 4 | allen | NULL |
+----+-------+--------+
3 rows in set (0.00 sec)#过滤出id在2和4之间的行
mysql> select * from student where id between 2 and 4;
+----+-------+--------+
| id | name | gender |
+----+-------+--------+
| 2 | alice | f |
| 3 | jack | NULL |
| 4 | allen | NULL |
+----+-------+--------+
3 rows in set (0.00 sec)#过滤name中以t开头的行,like模糊匹配,%匹配任意长度字符
mysql> select * from student where name like 't%';
+----+------+--------+
| id | name | gender |
+----+------+--------+
| 1 | tom | m |
+----+------+--------+
1 row in set (0.00 sec)#rlike正则表达式匹配带有l或者o的行
mysql> SELECT * FROM student WHERE name RLIKE '.*[lo].*';
+----+-------+--------+
| id | name | gender |
+----+-------+--------+
| 1 | tom | m |
| 2 | alice | f |
| 4 | allen | NULL |
+----+-------+--------+
3 rows in set (0.01 sec)#字段别名
mysql> select id stuid,name as stuname from student;
+-------+---------+
| stuid | stuname |
+-------+---------+
| 1 | tom |
| 2 | alice |
| 3 | jack |
| 4 | allen |
+-------+---------+
4 rows in set (0.00 sec)#查询classid是1,3,5的匹配项
MariaDB [hellodb]> select * from students where classid in (1,3,5);
+-------+--------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+--------------+-----+--------+---------+-----------+
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
+-------+--------------+-----+--------+---------+-----------+#查询classid不是1,3,5的匹配项
MariaDB [hellodb]> select * from students where classid not in (1,3,5);
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
+-------+---------------+-----+--------+---------+-----------+
14 rows in set (0.00 sec)
范例:判断是否为NULL
MariaDB [hellodb]> select * from students where classid is null;
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+-------------+-----+--------+---------+-----------+
2 rows in set (0.00 sec)#使用 <=> 运算符来比较classid列与NULL的值。该运算符返回以下结果:如果 classid 列的值为 NULL,则返回 1(真)。
MariaDB [hellodb]> select * from students where classid <=> null;
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+-------------+-----+--------+---------+-----------+
2 rows in set (0.00 sec)MariaDB [hellodb]> select * from students where classid is not null;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
+-------+---------------+-----+--------+---------+-----------+
23 rows in set (0.00 sec)#ifnull函数判断指定的字段是否为空值,如果classID的值为 NULL,则将其替换为字符串 '无班级'
MariaDB [hellodb]> select stuid,name,ifnull(classID,'无班级') from students where classid is null;
+-------+-------------+-----------------------------+
| stuid | name | ifnull(classID,'无班级') |
+-------+-------------+-----------------------------+
| 24 | Xu Xian | 无班级 |
| 25 | Sun Dasheng | 无班级 |
+-------+-------------+-----------------------------+
2 rows in set (0.00 sec)
范例: 记录去重
MariaDB [hellodb]> select distinct gender from students;
+--------+
| gender |
+--------+
| M |
| F |
+--------+
2 rows in set (0.00 sec)#将age和gender多个字段重复的记录去重
mysql> select distinct age,gender from students;
范例:SQL 注入攻击
# 这条语句使用逻辑 OR 操作符,将 password 的比较条件设置为一个始终为真('1'='1')的表达式。这使得整个 WHERE 条件永远成立,从而绕过密码验证并返回所有用户记录。
select * from user where name='admin' and password='' or '1'='1';
#与第一个示例类似,只是直接将 '1=1' 作为字符串赋给了 password 字段
select * from user where name='admin' and password='' or '1=1';
#使用了SQL注释符号 (--) 和单引号 (') 来注释掉后面包含用户名和密码比较的部分。这样,查询将只检查用户名,并忽略密码验证。
select * from user where name='admin'; -- ' and password='magedu123';
#与第三个类似,注释符号换位(#)
select * from user where name='admin'; # ' and password='magedu123';
范例: 分页查询
#只取前三个
MariaDB [hellodb]> select * from students limit 0,3;
MariaDB [hellodb]> select * from students limit 3;
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
+-------+-------------+-----+--------+---------+-----------+
3 rows in set (0.00 sec)#跳过第一个,取前三个
MariaDB [hellodb]> select * from students limit 1,3;
+-------+------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+------------+-----+--------+---------+-----------+
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
+-------+------------+-----+--------+---------+-----------+
3 rows in set (0.00 sec)# 查询第n页的数据,每页显示m条记录
mysql> select * from students limit (n-1) * m,m;
范例: 聚合函数
#对age年龄计算出总和除以行数量,性别为M平均年龄
MariaDB [hellodb]> select sum(age)/count(*) from students where gender ='M';
+-------------------+
| sum(age)/count(*) |
+-------------------+
| 33.0000 |
+-------------------+
1 row in set (0.00 sec)#对age年龄计算出总和除以行数量,性别为F平均年龄
MariaDB [hellodb]> select sum(age)/count(*) from students where gender ='F';
+-------------------+
| sum(age)/count(*) |
+-------------------+
| 19.0000 |
+-------------------+
1 row in set (0.00 sec)
范例:分组统计
#对classid班级进行分组统计学生数量
MariaDB [hellodb]> select classid,count(*) 数量 from students group by classid;
+---------+--------+
| classid | 数量 |
+---------+--------+
| NULL | 2 |
| 1 | 4 |
| 2 | 3 |
| 3 | 4 |
| 4 | 4 |
| 5 | 1 |
| 6 | 4 |
| 7 | 3 |
+---------+--------+
8 rows in set (0.00 sec)#展示不同班级和性别分组的学生数量
MariaDB [hellodb]> select classid,gender, count(*) 数量 from students group by classid,gender;
+---------+--------+--------+
| classid | gender | 数量 |
+---------+--------+--------+
| NULL | M | 2 |
| 1 | F | 2 |
| 1 | M | 2 |
| 2 | M | 3 |
| 3 | F | 3 |
| 3 | M | 1 |
| 4 | M | 4 |
| 5 | M | 1 |
| 6 | F | 3 |
| 6 | M | 1 |
| 7 | F | 2 |
| 7 | M | 1 |
+---------+--------+--------+
12 rows in set (0.00 sec)#对classid>3的进行过滤,对classid分组,使用avg函数求平均值,最后使用having过滤出平均年龄大于30岁的分组
MariaDB [hellodb]> select classid,avg(age) as 平均年龄 from students where classid > 3 group by classid having 平均年龄 >30;
+---------+--------------+
| classid | 平均年龄 |
+---------+--------------+
| 5 | 46.0000 |
+---------+--------------+
1 row in set (0.00 sec)#对gender分组,求平均年龄,过滤出性别为M的分组
select gender,avg(age) 平均年龄 from students group by gender having gender='M';#多个字段分组统计
select classid,gender,count(*) 数量 from students group by classid,gender;
select classid,gender,count(*) 数量 from students group by gender,classid;
范例: group_concat函数实现分组信息的集合
#对gender列进行分组,使用聚合函数GROUP_CONCAT()对分组中的name列进行连接,连接成一个字符串并以逗号作为默认分隔符。
MariaDB [hellodb]> select gender,group_concat(name) from students group by gender;
+--------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| gender | group_concat(name) |
+--------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| F | Lin Daiyu,Yue Lingshan,Ren Yingying,Wen Qingqing,Xi Ren,Diao Chan,Huang Yueying,Xiao Qiao,Lu Wushuang,Xue Baochai |
| M | Hua Rong,Shi Zhongyu,Ma Chao,Xu Xian,Lin Chong,Xu Zhu,Duan Yu,Tian Boguang,Yuan Chengzhi,Shi Qing,Yu Yutong,Ding Dian,Xie Yanke,Shi Potian,Sun Dasheng |
+--------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
范例: 分组统计
#使用 WITH ROLLUP 子句可以生成子总计行和总计行,“NULL”行代表了整体的总计,显示所有性别之和
MariaDB [hellodb]> select gender,count(*) from students group by gender with rollup;
+--------+----------+
| gender | count(*) |
+--------+----------+
| F | 10 |
| M | 15 |
| NULL | 25 |
+--------+----------+
3 rows in set (0.00 sec)MariaDB [hellodb]> select gender,group_concat(name) from students group by gender with rollup;
范例: 分组统计
#注意:一旦使用分组group by,在select后面的只能采用分组的列和聚合函数,其它的列不能放在select后面,否则根据系统变量SQL_MODE的值不同而不同的结果
#以下为MySQL8.0.17 的执行结果
mysql> use hellodb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -ADatabase changed
mysql> select classid,count(*) 数量 from students group by classid;
+---------+--------+
| classid | 数量 |
+---------+--------+
| 2 | 3 |
| 1 | 4 |
| 4 | 4 |
| 3 | 4 |
| 5 | 1 |
| 7 | 3 |
| 6 | 4 |
| NULL | 2 |
+---------+--------+
8 rows in set (0.00 sec)mysql> select classid,count(*),stuid 数量 from students group by classid;
ERROR 1055 (42000): Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'hellodb.students.StuID' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
#SELECT列表的表达式#3不在GROUP BY子句中,它包含非聚合列的hellodb.Student.StuID’,它在功能上不依赖于GROUP BY子句中的列; 这与 sql_mode=only_full_group_by不兼容mysql> select @@sql_mode;
+-----------------------------------------------------------------------------------------------------------------------+
| @@sql_mode |
+-----------------------------------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+-----------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)#以下是Mariadb10.3.17的执行结果,能显示结果,能看到stuid默认是表中classid对应的第一个值
MariaDB [hellodb]> select classid, count(*), stuid from students group by classid;
+---------+----------+-------+
| classid | count(*) | stuid |
+---------+----------+-------+
| NULL | 2 | 24 |
| 1 | 4 | 2 |
| 2 | 3 | 1 |
| 3 | 4 | 5 |
| 4 | 4 | 4 |
| 5 | 1 | 6 |
| 6 | 4 | 9 |
| 7 | 3 | 8 |
+---------+----------+-------+
8 rows in set (0.00 sec)#mariadb没有ONLY_FULL_GROUP_BY值
MariaDB [hellodb]> select @@sql_mode;
+--------------------------------------------------------------------------------
-----------+
| @@sql_mode
|
+--------------------------------------------------------------------------------
-----------+
|
STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+--------------------------------------------------------------------------------
-----------+
1 row in set (0.000 sec)
范例: 排序
select classid,sum(age) from students group by classid having classid is not null order by classid;
#只取前3个
mysql> select * from students order by age desc limit 3;
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
+-------+-------------+-----+--------+---------+-----------+
3 rows in set (0.00 sec)#跳过前3个只显示后续的2个
mysql> select * from students order by age desc limit 3,2;
+-------+--------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+--------------+-----+--------+---------+-----------+
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 4 | Ding Dian | 32 | M | 4 | 4 |
+-------+--------------+-----+--------+---------+-----------+
2 rows in set (0.00 sec)
范例: 排序
#先过滤再分组快一点,因为先过滤完了再分组较快,如果先分组数据较多分完组后再过滤掉导致白白分组
select classid,sum(age) from students where classid is not null group by classid order by classid;
select classid,sum(age) from students group by classid having classid is not null order by classid;
select classid,sum(age) from students where classid is not null group by classid order by classid limit 2,3;#必须先过滤,再排序
select * from students where classid is not null order by gender desc, age asc ;
#多列排序
select * from students order by gender desc, age asc;
范例:正序排序时将NULL记录排在最后
#对classid 正序排序,NULL记录排在最后 -对classid进行取反操作
select * from students order by -classid desc ;
范例:分组和排序
mysql> select classid,count(*) 数量 from students group by classid order by 数量;
+---------+--------+
| classid | 数量 |
+---------+--------+
| 5 | 1 |
| NULL | 2 |
| 2 | 3 |
| 7 | 3 |
| 1 | 4 |
| 4 | 4 |
| 3 | 4 |
| 6 | 4 |
+---------+--------+
8 rows in set (0.00 sec)#分组后再排序
mysql> select gender,classid,avg(age) from students where classid is not null group by gender,classid order by gender,classid;
+--------+---------+----------+
| gender | classid | avg(age) |
+--------+---------+----------+
| F | 1 | 19.5000 |
| F | 3 | 18.3333 |
| F | 6 | 20.0000 |
| F | 7 | 18.0000 |
| M | 1 | 21.5000 |
| M | 2 | 36.0000 |
| M | 3 | 26.0000 |
| M | 4 | 24.7500 |
| M | 5 | 46.0000 |
| M | 6 | 23.0000 |
| M | 7 | 23.0000 |
+--------+---------+----------+
11 rows in set (0.00 sec)#对年龄排序显示前10个
mysql> select * from students order by age limit 10;
+-------+--------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+--------------+-----+--------+---------+-----------+
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
+-------+--------------+-----+--------+---------+-----------+
10 rows in set (0.00 sec)#对年龄排序,跳过前3个,只显示后续10个
mysql> select * from students order by age limit 3,10;
+-------+--------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+--------------+-----+--------+---------+-----------+
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
+-------+--------------+-----+--------+---------+-----------+
10 rows in set (0.00 sec)#distinct去除重复行并排序,显示前3个
mysql> select distinct age from students order by age limit 3 ;
+-----+
| age |
+-----+
| 17 |
| 18 |
| 19 |
+-----+
3 rows in set (0.00 sec)#distinct去除重复行并排序,跳过前3显示后续5个
mysql> select distinct age from students order by age limit 3,5 ;
+-----+
| age |
+-----+
| 20 |
| 21 |
| 22 |
| 23 |
| 25 |
范例: 分组和排序的次序
#顺序: group by,having,order by 先分组再过滤再排序
mysql> select classid,count(*) from students group by classid having classid is not null order by classid;
+---------+----------+
| classid | count(*) |
+---------+----------+
| 1 | 4 |
| 2 | 3 |
| 3 | 4 |
| 4 | 4 |
| 5 | 1 |
| 6 | 4 |
| 7 | 3 |
+---------+----------+
7 rows in set (0.00 sec)#以下顺序会出错,group by,order by,having
mysql> select classid,count(*) from students group by classid order by classid having classid is not null;
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 'having classid is not null' #以下顺序会出错,order by,group by,having
mysql> select classid,count(*) from students order by classid group by classid having classid is not null;
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 'group by classid having classid is not null' at line 1
范例:时间字段进行过滤查询,并且timestamp可以随其它字段的更新自动更新
mysql> create table testdate (id int auto_increment primary key,date-> timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.01 sec)mysql> insert testdate () values();
Query OK, 1 row affected (0.00 sec)mysql> insert testdate values(),(),();
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0mysql> select * from testdate;
+----+---------------------+
| id | date |
+----+---------------------+
| 1 | 2023-08-09 12:53:38 |
| 2 | 2023-08-09 12:53:42 |
| 3 | 2023-08-09 12:53:42 |
| 4 | 2023-08-09 12:53:42 |
+----+---------------------+
4 rows in set (0.00 sec)mysql> select * from testdate where date between '2023-08-09 12:53:38' and '2023-08-09 12:53:42';
+----+---------------------+
| id | date |
+----+---------------------+
| 1 | 2023-08-09 12:53:38 |
| 2 | 2023-08-09 12:53:42 |
| 3 | 2023-08-09 12:53:42 |
| 4 | 2023-08-09 12:53:42 |
+----+---------------------+
4 rows in set (0.00 sec)mysql> select * from testdate where date >='2023-08-09 12:53:38 ' and date <='2023-08-09 12:53:42';
+----+---------------------+
| id | date |
+----+---------------------+
| 1 | 2023-08-09 12:53:38 |
| 2 | 2023-08-09 12:53:42 |
| 3 | 2023-08-09 12:53:42 |
| 4 | 2023-08-09 12:53:42 |
+----+---------------------+
4 rows in set, 1 warning (0.00 sec)#修改其它字段,会自动更新timestamp字段
mysql> update testdate set id=10 where id=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0mysql> select * from testdate;
+----+---------------------+
| id | date |
+----+---------------------+
| 2 | 2023-08-09 12:53:42 |
| 3 | 2023-08-09 12:53:42 |
| 4 | 2023-08-09 12:53:42 |
| 5 | 2023-08-09 12:54:30 |
| 10 | 2023-08-09 12:56:18 |
+----+---------------------+
5 rows in set (0.00 sec)
1.7.2 多表查询
多表查询,即查询结果来自于多张表
-
子查询:在SQL语句嵌套着查询语句,性能较差,基于某语句的查询结果再次进行的查询
-
联合查询:UNION
-
交叉连接:笛卡尔乘积 CROSS JOIN
-
内连接:
-
等值连接:让表之间的字段以"等值"建立连接关系
-
不等值连接
-
自然连接:去掉重复列的等值连接 , 语法: FROM table1 NATURAL JOIN table2;
-
外连接:
-
左外连接:FROM tb1 LEFT JOIN tb2 ON tb1.col=tb2.col
-
右外连接:FROM tb1 RIGHT JOIN tb2 ON tb1.col=tb2.col
完全外连接: FROM tb1 FULL OUTER JOIN tb2 ON tb1.col=tb2.col 注意:MySQL 不支持此SQL语法
-
自连接:本表和本表进行连接查询
子查询
子查询 subquery 即SQL语句调用另一个SELECT子句,可以是对同一张表,也可以是对不同表,主要有以下四种常见的用法.
-
用于比较表达式中的子查询;子查询仅能返回单个值
#查询students表中age大于teachers表的平均年龄的大的人 SELECT Name,Age FROM students WHERE Age>(SELECT avg(Age) FROM teachers); #将stuid=25的年龄修改为teachers表的平均年龄 update students set Age=(SELECT avg(Age) FROM teachers) where stuid=25;
-
用于IN中的子查询:子查询应该单独查询并返回一个或多个值重新构成列表
#查询students表中年龄是否有符合teachers表的平均年龄条件的人 SELECT Name,Age FROM students WHERE Age IN (SELECT Age FROM teachers);
-
用于EXISTS 和 Not EXISTS
参考链接:https://dev.mysql.com/doc/refman/8.0/en/exists-and-not-exists-subqueries.html
EXISTS(包括 NOT EXISTS )子句的返回值是一个BOOL值。 EXISTS 内部有一个子查询语句(SELECT... FROM...), 将其称为EXIST的内查询语句。其内查询语句返回一个结果集。 EXISTS子句根据其内查询语句的结果集空或者非空,返回一个布尔值。将外查询表的每一行,代入内查询作为检验,如果内查询返回的结果为非空值,则EXISTS子句返回TRUE,外查询的这一行数据便可作为外查询的结果行返回,否则不能作为结果
mysql> select * from students s where EXISTS (select * from teachers t where s.teacherid=t.tid);
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
+-------+-------------+-----+--------+---------+-----------+
3 rows in set (0.00 sec)#说明:
1、EXISTS (或 NOT EXISTS) 用在 where之后,且后面紧跟子查询语句(带括号)
2、EXISTS (或 NOT EXISTS) 只关心子查询有没有结果,并不关心子查询的结果具体是什么
3、上述语句把students的记录逐条代入到Exists后面的子查询中,如果子查询结果集不为空,即说明存在,那么这条students的记录出现在最终结果集,否则被排除mysql> select * from students s where NOT EXISTS (select * from teachers t where s.teacherid=t.tid);
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 77 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
22 rows in set (0.00 sec)
- 用于FROM子句中的子查询
使用格式:
SELECT tb_alias.col1,... FROM (SELECT clause) AS tb_alias WHERE Clause;
范例:
#对子查询的结果起个别名为s,列出平均年龄aage大于30的记录
mysql> SELECT s.ClassID,s.aage FROM (SELECT ClassID,avg(Age) AS aage FROM students WHERE ClassID IS NOT NULL GROUP BY ClassID) AS s WHERE s.aage>30;
+---------+---------+
| ClassID | aage |
+---------+---------+
| 2 | 36.0000 |
| 5 | 46.0000 |
+---------+---------+
2 rows in set (0.00 sec)#子查询结果
mysql> select classid,avg(age) as aage from students where classid is not null group by classid;
+---------+---------+
| classid | aage |
+---------+---------+
| 2 | 36.0000 |
| 1 | 20.5000 |
| 4 | 24.7500 |
| 3 | 20.2500 |
| 5 | 46.0000 |
| 7 | 19.6667 |
| 6 | 20.7500 |
+---------+---------+
7 rows in set (0.00 sec)
范例:子查询
#子查询:select 的执行结果,被其它SQL调用
mysql> select stuid,name,age from students where age > (select avg(age) from students);
+-------+--------------+-----+
| stuid | name | age |
+-------+--------------+-----+
| 3 | Xie Yanke | 53 |
| 4 | Ding Dian | 32 |
| 6 | Shi Qing | 46 |
| 13 | Tian Boguang | 33 |
| 24 | Xu Xian | 27 |
| 25 | Sun Dasheng | 77 |
+-------+--------------+-----+
6 rows in set (0.00 sec)
范例:子查询用于更新表
mysql> update teachers set age=(select avg(age) from students) where tid=4;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0mysql> select * from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 26 | F |
+-----+---------------+-----+--------+
4 rows in set (0.00 sec)
子查询优化
子查询可以一次性完成很多逻辑上需要多个步骤才能完成的SQL操作。子查询虽然可以使查询语句很灵活,但执行效率不高。执行子查询时,需要为内层查询语句的查询结果建立一个临时表。然后外层查询语句从临时表中查询记录。查询完毕后,再撤销这些临时表。因此,子查询的速度会受到一定的影响。如果查询的数据量比较大,这种影响就会随之增大。
可以使用连接(JOIN)查询来替代子查询。连接查询不需要建立临时表,其速度比子查询要快,如果查询中使用到索引的话,性能会更好。
联合查询
联合查询 Union 实现的条件,多个表的字段数量相同,字段名和数据类型可以不同,但一般数据类型是相同的.
SELECT Name,Age FROM students UNION SELECT Name,Age FROM teachers;
范例:联合查询
#多表纵向合并union
mysql> select tid as id,name,age,gender from teachers union select stuid,name,age,gender from students;
+----+---------------+-----+--------+
| id | name | age | gender |
+----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 26 | F |
| 1 | Shi Zhongyu | 22 | M |
| 2 | Shi Potian | 22 | M |
| 3 | Xie Yanke | 53 | M |
| 4 | Ding Dian | 32 | M |
| 5 | Yu Yutong | 26 | M |
| 6 | Shi Qing | 46 | M |
| 7 | Xi Ren | 19 | F |
| 8 | Lin Daiyu | 17 | F |
| 9 | Ren Yingying | 20 | F |
| 10 | Yue Lingshan | 19 | F |
| 11 | Yuan Chengzhi | 23 | M |
| 12 | Wen Qingqing | 19 | F |
| 13 | Tian Boguang | 33 | M |
| 14 | Lu Wushuang | 17 | F |
| 15 | Duan Yu | 19 | M |
| 16 | Xu Zhu | 21 | M |
| 17 | Lin Chong | 25 | M |
| 18 | Hua Rong | 23 | M |
| 19 | Xue Baochai | 18 | F |
| 20 | Diao Chan | 19 | F |
| 21 | Huang Yueying | 22 | F |
| 22 | Xiao Qiao | 20 | F |
| 23 | Ma Chao | 23 | M |
| 24 | Xu Xian | 27 | M |
| 25 | Sun Dasheng | 77 | M |
+----+---------------+-----+--------+
29 rows in set (0.00 sec)#union去重,仅返回不重复的记录
mysql> select * from teachers union select * from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 26 | F |
+-----+---------------+-----+--------+
4 rows in set (0.00 sec)#union all将两个查询的结果集合并在一起,包括重复行。
mysql> select * from teachers union all select *from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 26 | F |
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 26 | F |
+-----+---------------+-----+--------+
8 rows in set (0.00 sec)#distinct去除重复数据,确保每一行都是唯一的
mysql> select distinct * from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 26 | F |
+-----+---------------+-----+--------+
4 rows in set (0.00 sec)
范例: 去重记录
mysql> select * from emp;
+-----+-------+------+--------+
| tid | Name | Age | Gender |
+-----+-------+------+--------+
| 16 | Song | 45 | M |
| 17 | Zhang | 94 | M |
| 18 | mage | 20 | M |
| 18 | mage | 20 | M |
| 180 | li | 22 | F |
+-----+-------+------+--------+
5 rows in set (0.00 sec)mysql> select distinct * from emp;
+-----+-------+------+--------+
| tid | Name | Age | Gender |
+-----+-------+------+--------+
| 16 | Song | 45 | M |
| 17 | Zhang | 94 | M |
| 18 | mage | 20 | M |
| 180 | li | 22 | F |
+-----+-------+------+--------+
4 rows in set (0.00 sec)mysql> select * from emp union select * from emp;
+-----+-------+------+--------+
| tid | Name | Age | Gender |
+-----+-------+------+--------+
| 16 | Song | 45 | M |
| 17 | Zhang | 94 | M |
| 18 | mage | 20 | M |
| 180 | li | 22 | F |
+-----+-------+------+--------+
4 rows in set (0.00 sec)#union all 不去重
mysql> select * from emp union all select * from emp;
+-----+-------+------+--------+
| tid | Name | Age | Gender |
+-----+-------+------+--------+
| 16 | Song | 45 | M |
| 17 | Zhang | 94 | M |
| 18 | mage | 20 | M |
| 18 | mage | 20 | M |
| 180 | li | 22 | F |
| 16 | Song | 45 | M |
| 17 | Zhang | 94 | M |
| 18 | mage | 20 | M |
| 18 | mage | 20 | M |
| 180 | li | 22 | F |
+-----+-------+------+--------+
10 rows in set (0.00 sec)
交叉连接
cross join 即多表的记录之间做笛卡尔乘积组合,并且多个表的列横向合并相加, "雨露均沾"
比如: 第一个表3行4列,第二个表5行6列,cross join后的结果为3*5=15行,4+6=10列
交叉连接生成的记录可能会非常多,建议慎用
范例:交叉连接
##横向合并,交叉连接(横向笛卡尔)
MariaDB [hellodb]> select * from teachers , students; #,在from列出多个表时默认执行交叉连接
mysql> select * from students cross join teachers;
+-------+---------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+---------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 4 | Lin Chaoying | 26 | F |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 3 | Miejue Shitai | 77 | F |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 2 | Zhang Sanfeng | 94 | M |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 1 | Song Jiang | 45 | M |
| 2 | Shi Potian | 22 | M | 1 | 7 | 4 | Lin Chaoying | 26 | F |
| 2 | Shi Potian | 22 | M | 1 | 7 | 3 | Miejue Shitai | 77 | F |
| 2 | Shi Potian | 22 | M | 1 | 7 | 2 | Zhang Sanfeng | 94 | M |
| 2 | Shi Potian | 22 | M | 1 | 7 | 1 | Song Jiang | 45 | M |
| 3 | Xie Yanke | 53 | M | 2 | 16 | 4 | Lin Chaoying | 26 | F |
| 3 | Xie Yanke | 53 | M | 2 | 16 | 3 | Miejue Shitai | 77 | F |
| 3 | Xie Yanke | 53 | M | 2 | 16 | 2 | Zhang Sanfeng | 94 | M |
| 3 | Xie Yanke | 53 | M | 2 | 16 | 1 | Song Jiang | 45 | M |
| 4 | Ding Dian | 32 | M | 4 | 4 | 4 | Lin Chaoying | 26 | F |
| 4 | Ding Dian | 32 | M | 4 | 4 | 3 | Miejue Shitai | 77 | F |
| 4 | Ding Dian | 32 | M | 4 | 4 | 2 | Zhang Sanfeng | 94 | M |
| 4 | Ding Dian | 32 | M | 4 | 4 | 1 | Song Jiang | 45 | M |
| 5 | Yu Yutong | 26 | M | 3 | 1 | 4 | Lin Chaoying | 26 | F |
| 5 | Yu Yutong | 26 | M | 3 | 1 | 3 | Miejue Shitai | 77 | F |
| 5 | Yu Yutong | 26 | M | 3 | 1 | 2 | Zhang Sanfeng | 94 | M |
| 5 | Yu Yutong | 26 | M | 3 | 1 | 1 | Song Jiang | 45 | M |
| 6 | Shi Qing | 46 | M | 5 | NULL | 4 | Lin Chaoying | 26 | F |
| 6 | Shi Qing | 46 | M | 5 | NULL | 3 | Miejue Shitai | 77 | F |
| 6 | Shi Qing | 46 | M | 5 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 6 | Shi Qing | 46 | M | 5 | NULL | 1 | Song Jiang | 45 | M |
| 7 | Xi Ren | 19 | F | 3 | NULL | 4 | Lin Chaoying | 26 | F |
| 7 | Xi Ren | 19 | F | 3 | NULL | 3 | Miejue Shitai | 77 | F |
| 7 | Xi Ren | 19 | F | 3 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 7 | Xi Ren | 19 | F | 3 | NULL | 1 | Song Jiang | 45 | M |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | 4 | Lin Chaoying | 26 | F |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | 3 | Miejue Shitai | 77 | F |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | 1 | Song Jiang | 45 | M |
| 9 | Ren Yingying | 20 | F | 6 | NULL | 4 | Lin Chaoying | 26 | F |
| 9 | Ren Yingying | 20 | F | 6 | NULL | 3 | Miejue Shitai | 77 | F |
| 9 | Ren Yingying | 20 | F | 6 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 9 | Ren Yingying | 20 | F | 6 | NULL | 1 | Song Jiang | 45 | M |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | 4 | Lin Chaoying | 26 | F |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | 3 | Miejue Shitai | 77 | F |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | 1 | Song Jiang | 45 | M |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | 4 | Lin Chaoying | 26 | F |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | 3 | Miejue Shitai | 77 | F |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | 1 | Song Jiang | 45 | M |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | 4 | Lin Chaoying | 26 | F |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | 3 | Miejue Shitai | 77 | F |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | 1 | Song Jiang | 45 | M |
| 13 | Tian Boguang | 33 | M | 2 | NULL | 4 | Lin Chaoying | 26 | F |
| 13 | Tian Boguang | 33 | M | 2 | NULL | 3 | Miejue Shitai | 77 | F |
| 13 | Tian Boguang | 33 | M | 2 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 13 | Tian Boguang | 33 | M | 2 | NULL | 1 | Song Jiang | 45 | M |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | 4 | Lin Chaoying | 26 | F |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | 3 | Miejue Shitai | 77 | F |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | 1 | Song Jiang | 45 | M |
| 15 | Duan Yu | 19 | M | 4 | NULL | 4 | Lin Chaoying | 26 | F |
| 15 | Duan Yu | 19 | M | 4 | NULL | 3 | Miejue Shitai | 77 | F |
| 15 | Duan Yu | 19 | M | 4 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 15 | Duan Yu | 19 | M | 4 | NULL | 1 | Song Jiang | 45 | M |
| 16 | Xu Zhu | 21 | M | 1 | NULL | 4 | Lin Chaoying | 26 | F |
| 16 | Xu Zhu | 21 | M | 1 | NULL | 3 | Miejue Shitai | 77 | F |
| 16 | Xu Zhu | 21 | M | 1 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 16 | Xu Zhu | 21 | M | 1 | NULL | 1 | Song Jiang | 45 | M |
| 17 | Lin Chong | 25 | M | 4 | NULL | 4 | Lin Chaoying | 26 | F |
| 17 | Lin Chong | 25 | M | 4 | NULL | 3 | Miejue Shitai | 77 | F |
| 17 | Lin Chong | 25 | M | 4 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 17 | Lin Chong | 25 | M | 4 | NULL | 1 | Song Jiang | 45 | M |
| 18 | Hua Rong | 23 | M | 7 | NULL | 4 | Lin Chaoying | 26 | F |
| 18 | Hua Rong | 23 | M | 7 | NULL | 3 | Miejue Shitai | 77 | F |
| 18 | Hua Rong | 23 | M | 7 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 18 | Hua Rong | 23 | M | 7 | NULL | 1 | Song Jiang | 45 | M |
| 19 | Xue Baochai | 18 | F | 6 | NULL | 4 | Lin Chaoying | 26 | F |
| 19 | Xue Baochai | 18 | F | 6 | NULL | 3 | Miejue Shitai | 77 | F |
| 19 | Xue Baochai | 18 | F | 6 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 19 | Xue Baochai | 18 | F | 6 | NULL | 1 | Song Jiang | 45 | M |
| 20 | Diao Chan | 19 | F | 7 | NULL | 4 | Lin Chaoying | 26 | F |
| 20 | Diao Chan | 19 | F | 7 | NULL | 3 | Miejue Shitai | 77 | F |
| 20 | Diao Chan | 19 | F | 7 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 20 | Diao Chan | 19 | F | 7 | NULL | 1 | Song Jiang | 45 | M |
| 21 | Huang Yueying | 22 | F | 6 | NULL | 4 | Lin Chaoying | 26 | F |
| 21 | Huang Yueying | 22 | F | 6 | NULL | 3 | Miejue Shitai | 77 | F |
| 21 | Huang Yueying | 22 | F | 6 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 21 | Huang Yueying | 22 | F | 6 | NULL | 1 | Song Jiang | 45 | M |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | 4 | Lin Chaoying | 26 | F |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | 3 | Miejue Shitai | 77 | F |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | 1 | Song Jiang | 45 | M |
| 23 | Ma Chao | 23 | M | 4 | NULL | 4 | Lin Chaoying | 26 | F |
| 23 | Ma Chao | 23 | M | 4 | NULL | 3 | Miejue Shitai | 77 | F |
| 23 | Ma Chao | 23 | M | 4 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 23 | Ma Chao | 23 | M | 4 | NULL | 1 | Song Jiang | 45 | M |
| 24 | Xu Xian | 27 | M | NULL | NULL | 4 | Lin Chaoying | 26 | F |
| 24 | Xu Xian | 27 | M | NULL | NULL | 3 | Miejue Shitai | 77 | F |
| 24 | Xu Xian | 27 | M | NULL | NULL | 2 | Zhang Sanfeng | 94 | M |
| 24 | Xu Xian | 27 | M | NULL | NULL | 1 | Song Jiang | 45 | M |
| 25 | Sun Dasheng | 77 | M | NULL | NULL | 4 | Lin Chaoying | 26 | F |
| 25 | Sun Dasheng | 77 | M | NULL | NULL | 3 | Miejue Shitai | 77 | F |
| 25 | Sun Dasheng | 77 | M | NULL | NULL | 2 | Zhang Sanfeng | 94 | M |
| 25 | Sun Dasheng | 77 | M | NULL | NULL | 1 | Song Jiang | 45 | M |
+-------+---------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
100 rows in set (0.00 sec)#为字段students.name别名student_name,teachers.name别名teacher_name。相同名称字段过滤前面需要加表名
mysql> select stuid,students.name-> student_name,students.age,tid,teachers.name teacher_name,teachers.age from-> teachers cross join students ;
+-------+---------------+-----+-----+---------------+-----+
| stuid | student_name | age | tid | teacher_name | age |
+-------+---------------+-----+-----+---------------+-----+
| 1 | Shi Zhongyu | 22 | 4 | Lin Chaoying | 26 |
| 1 | Shi Zhongyu | 22 | 3 | Miejue Shitai | 77 |
| 1 | Shi Zhongyu | 22 | 2 | Zhang Sanfeng | 94 |
| 1 | Shi Zhongyu | 22 | 1 | Song Jiang | 45 |
| 2 | Shi Potian | 22 | 4 | Lin Chaoying | 26 |
| 2 | Shi Potian | 22 | 3 | Miejue Shitai | 77 |
| 2 | Shi Potian | 22 | 2 | Zhang Sanfeng | 94 |
| 2 | Shi Potian | 22 | 1 | Song Jiang | 45 |
| 3 | Xie Yanke | 53 | 4 | Lin Chaoying | 26 |
| 3 | Xie Yanke | 53 | 3 | Miejue Shitai | 77 |
| 3 | Xie Yanke | 53 | 2 | Zhang Sanfeng | 94 |
| 3 | Xie Yanke | 53 | 1 | Song Jiang | 45 |
| 4 | Ding Dian | 32 | 4 | Lin Chaoying | 26 |
| 4 | Ding Dian | 32 | 3 | Miejue Shitai | 77 |
| 4 | Ding Dian | 32 | 2 | Zhang Sanfeng | 94 |
| 4 | Ding Dian | 32 | 1 | Song Jiang | 45 |
| 5 | Yu Yutong | 26 | 4 | Lin Chaoying | 26 |
| 5 | Yu Yutong | 26 | 3 | Miejue Shitai | 77 |
| 5 | Yu Yutong | 26 | 2 | Zhang Sanfeng | 94 |
| 5 | Yu Yutong | 26 | 1 | Song Jiang | 45 |
| 6 | Shi Qing | 46 | 4 | Lin Chaoying | 26 |
| 6 | Shi Qing | 46 | 3 | Miejue Shitai | 77 |
| 6 | Shi Qing | 46 | 2 | Zhang Sanfeng | 94 |
| 6 | Shi Qing | 46 | 1 | Song Jiang | 45 |
| 7 | Xi Ren | 19 | 4 | Lin Chaoying | 26 |
| 7 | Xi Ren | 19 | 3 | Miejue Shitai | 77 |
| 7 | Xi Ren | 19 | 2 | Zhang Sanfeng | 94 |
| 7 | Xi Ren | 19 | 1 | Song Jiang | 45 |
| 8 | Lin Daiyu | 17 | 4 | Lin Chaoying | 26 |
| 8 | Lin Daiyu | 17 | 3 | Miejue Shitai | 77 |
| 8 | Lin Daiyu | 17 | 2 | Zhang Sanfeng | 94 |
| 8 | Lin Daiyu | 17 | 1 | Song Jiang | 45 |
| 9 | Ren Yingying | 20 | 4 | Lin Chaoying | 26 |
| 9 | Ren Yingying | 20 | 3 | Miejue Shitai | 77 |
| 9 | Ren Yingying | 20 | 2 | Zhang Sanfeng | 94 |
| 9 | Ren Yingying | 20 | 1 | Song Jiang | 45 |
| 10 | Yue Lingshan | 19 | 4 | Lin Chaoying | 26 |
| 10 | Yue Lingshan | 19 | 3 | Miejue Shitai | 77 |
| 10 | Yue Lingshan | 19 | 2 | Zhang Sanfeng | 94 |
| 10 | Yue Lingshan | 19 | 1 | Song Jiang | 45 |
| 11 | Yuan Chengzhi | 23 | 4 | Lin Chaoying | 26 |
| 11 | Yuan Chengzhi | 23 | 3 | Miejue Shitai | 77 |
| 11 | Yuan Chengzhi | 23 | 2 | Zhang Sanfeng | 94 |
| 11 | Yuan Chengzhi | 23 | 1 | Song Jiang | 45 |
| 12 | Wen Qingqing | 19 | 4 | Lin Chaoying | 26 |
| 12 | Wen Qingqing | 19 | 3 | Miejue Shitai | 77 |
| 12 | Wen Qingqing | 19 | 2 | Zhang Sanfeng | 94 |
| 12 | Wen Qingqing | 19 | 1 | Song Jiang | 45 |
| 13 | Tian Boguang | 33 | 4 | Lin Chaoying | 26 |
| 13 | Tian Boguang | 33 | 3 | Miejue Shitai | 77 |
| 13 | Tian Boguang | 33 | 2 | Zhang Sanfeng | 94 |
| 13 | Tian Boguang | 33 | 1 | Song Jiang | 45 |
| 14 | Lu Wushuang | 17 | 4 | Lin Chaoying | 26 |
| 14 | Lu Wushuang | 17 | 3 | Miejue Shitai | 77 |
| 14 | Lu Wushuang | 17 | 2 | Zhang Sanfeng | 94 |
| 14 | Lu Wushuang | 17 | 1 | Song Jiang | 45 |
| 15 | Duan Yu | 19 | 4 | Lin Chaoying | 26 |
| 15 | Duan Yu | 19 | 3 | Miejue Shitai | 77 |
| 15 | Duan Yu | 19 | 2 | Zhang Sanfeng | 94 |
| 15 | Duan Yu | 19 | 1 | Song Jiang | 45 |
| 16 | Xu Zhu | 21 | 4 | Lin Chaoying | 26 |
| 16 | Xu Zhu | 21 | 3 | Miejue Shitai | 77 |
| 16 | Xu Zhu | 21 | 2 | Zhang Sanfeng | 94 |
| 16 | Xu Zhu | 21 | 1 | Song Jiang | 45 |
| 17 | Lin Chong | 25 | 4 | Lin Chaoying | 26 |
| 17 | Lin Chong | 25 | 3 | Miejue Shitai | 77 |
| 17 | Lin Chong | 25 | 2 | Zhang Sanfeng | 94 |
| 17 | Lin Chong | 25 | 1 | Song Jiang | 45 |
| 18 | Hua Rong | 23 | 4 | Lin Chaoying | 26 |
| 18 | Hua Rong | 23 | 3 | Miejue Shitai | 77 |
| 18 | Hua Rong | 23 | 2 | Zhang Sanfeng | 94 |
| 18 | Hua Rong | 23 | 1 | Song Jiang | 45 |
| 19 | Xue Baochai | 18 | 4 | Lin Chaoying | 26 |
| 19 | Xue Baochai | 18 | 3 | Miejue Shitai | 77 |
| 19 | Xue Baochai | 18 | 2 | Zhang Sanfeng | 94 |
| 19 | Xue Baochai | 18 | 1 | Song Jiang | 45 |
| 20 | Diao Chan | 19 | 4 | Lin Chaoying | 26 |
| 20 | Diao Chan | 19 | 3 | Miejue Shitai | 77 |
| 20 | Diao Chan | 19 | 2 | Zhang Sanfeng | 94 |
| 20 | Diao Chan | 19 | 1 | Song Jiang | 45 |
| 21 | Huang Yueying | 22 | 4 | Lin Chaoying | 26 |
| 21 | Huang Yueying | 22 | 3 | Miejue Shitai | 77 |
| 21 | Huang Yueying | 22 | 2 | Zhang Sanfeng | 94 |
| 21 | Huang Yueying | 22 | 1 | Song Jiang | 45 |
| 22 | Xiao Qiao | 20 | 4 | Lin Chaoying | 26 |
| 22 | Xiao Qiao | 20 | 3 | Miejue Shitai | 77 |
| 22 | Xiao Qiao | 20 | 2 | Zhang Sanfeng | 94 |
| 22 | Xiao Qiao | 20 | 1 | Song Jiang | 45 |
| 23 | Ma Chao | 23 | 4 | Lin Chaoying | 26 |
| 23 | Ma Chao | 23 | 3 | Miejue Shitai | 77 |
| 23 | Ma Chao | 23 | 2 | Zhang Sanfeng | 94 |
| 23 | Ma Chao | 23 | 1 | Song Jiang | 45 |
| 24 | Xu Xian | 27 | 4 | Lin Chaoying | 26 |
| 24 | Xu Xian | 27 | 3 | Miejue Shitai | 77 |
| 24 | Xu Xian | 27 | 2 | Zhang Sanfeng | 94 |
| 24 | Xu Xian | 27 | 1 | Song Jiang | 45 |
| 25 | Sun Dasheng | 77 | 4 | Lin Chaoying | 26 |
| 25 | Sun Dasheng | 77 | 3 | Miejue Shitai | 77 |
| 25 | Sun Dasheng | 77 | 2 | Zhang Sanfeng | 94 |
| 25 | Sun Dasheng | 77 | 1 | Song Jiang | 45 |
+-------+---------------+-----+-----+---------------+-----+
100 rows in set (0.00 sec)#与上面的命令执行结果相同,将表起个别名查询,students别名s,teachers别名t
mysql> select stuid,s.name student_name,s.age student_age,tid,t.name teacher_name,t.age teacher_age from teachers t cross join students s;
内连接
inner join 内连接取多个表的交集
范例:内连接
#内连接inner join
#从students表和teachers表中获取数据,并将它们连接在一起,列出students.teacherid=teachers.tid相同的记录
mysql> select * from students inner join teachers on students.teacherid=teachers.tid;
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 3 | Miejue Shitai | 77 | F |
| 4 | Ding Dian | 32 | M | 4 | 4 | 4 | Lin Chaoying | 26 | F |
| 5 | Yu Yutong | 26 | M | 3 | 1 | 1 | Song Jiang | 45 | M |
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
3 rows in set (0.00 sec)#如果表定义了别名,原表名将无法使用
mysql> select stuid,s.name as student_name ,tid,t.name as teacher_name from students as s inner join teachers as t on s.teacherid=t.tid;
+-------+--------------+-----+---------------+
| stuid | student_name | tid | teacher_name |
+-------+--------------+-----+---------------+
| 1 | Shi Zhongyu | 3 | Miejue Shitai |
| 4 | Ding Dian | 4 | Lin Chaoying |
| 5 | Yu Yutong | 1 | Song Jiang |
+-------+--------------+-----+---------------+
3 rows in set (0.00 sec)mysql> select stuid,s.name studentname,s.age studentage,tid,t.name as teachername,t.age teacherage from students as s inner join teachers t on s.teacherid=t.tid;
+-------+-------------+------------+-----+---------------+------------+
| stuid | studentname | studentage | tid | teachername | teacherage |
+-------+-------------+------------+-----+---------------+------------+
| 1 | Shi Zhongyu | 22 | 3 | Miejue Shitai | 77 |
| 4 | Ding Dian | 32 | 4 | Lin Chaoying | 26 |
| 5 | Yu Yutong | 26 | 1 | Song Jiang | 45 |
+-------+-------------+------------+-----+---------------+------------+
3 rows in set (0.00 sec)mysql> select * from students , teachers where students.teacherid=teachers.tid;
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 3 | Miejue Shitai | 77 | F |
| 4 | Ding Dian | 32 | M | 4 | 4 | 4 | Lin Chaoying | 26 | F |
| 5 | Yu Yutong | 26 | M | 3 | 1 | 1 | Song Jiang | 45 | M |
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
3 rows in set (0.00 sec)#s.gender <> t.gender内连接条件为学生老师gender性别不相等
mysql> select s.name 学生姓名,s.age 学生年龄,s.gender 学生性别,t.name 老师姓名,t.age 老师年龄,t.gender 老师性别 from students s inner join teachers t on s.gender <> t.gender;
+---------------+--------------+--------------+---------------+--------------+--------------+
| 学生姓名 | 学生年龄 | 学生性别 | 老师姓名 | 老师年龄 | 老师性别 |
+---------------+--------------+--------------+---------------+--------------+--------------+
| Shi Zhongyu | 22 | M | Lin Chaoying | 26 | F |
| Shi Zhongyu | 22 | M | Miejue Shitai | 77 | F |
| Shi Potian | 22 | M | Lin Chaoying | 26 | F |
| Shi Potian | 22 | M | Miejue Shitai | 77 | F |
| Xie Yanke | 53 | M | Lin Chaoying | 26 | F |
| Xie Yanke | 53 | M | Miejue Shitai | 77 | F |
| Ding Dian | 32 | M | Lin Chaoying | 26 | F |
| Ding Dian | 32 | M | Miejue Shitai | 77 | F |
| Yu Yutong | 26 | M | Lin Chaoying | 26 | F |
| Yu Yutong | 26 | M | Miejue Shitai | 77 | F |
| Shi Qing | 46 | M | Lin Chaoying | 26 | F |
| Shi Qing | 46 | M | Miejue Shitai | 77 | F |
| Xi Ren | 19 | F | Zhang Sanfeng | 94 | M |
| Xi Ren | 19 | F | Song Jiang | 45 | M |
| Lin Daiyu | 17 | F | Zhang Sanfeng | 94 | M |
| Lin Daiyu | 17 | F | Song Jiang | 45 | M |
| Ren Yingying | 20 | F | Zhang Sanfeng | 94 | M |
| Ren Yingying | 20 | F | Song Jiang | 45 | M |
| Yue Lingshan | 19 | F | Zhang Sanfeng | 94 | M |
| Yue Lingshan | 19 | F | Song Jiang | 45 | M |
| Yuan Chengzhi | 23 | M | Lin Chaoying | 26 | F |
| Yuan Chengzhi | 23 | M | Miejue Shitai | 77 | F |
| Wen Qingqing | 19 | F | Zhang Sanfeng | 94 | M |
| Wen Qingqing | 19 | F | Song Jiang | 45 | M |
| Tian Boguang | 33 | M | Lin Chaoying | 26 | F |
| Tian Boguang | 33 | M | Miejue Shitai | 77 | F |
| Lu Wushuang | 17 | F | Zhang Sanfeng | 94 | M |
| Lu Wushuang | 17 | F | Song Jiang | 45 | M |
| Duan Yu | 19 | M | Lin Chaoying | 26 | F |
| Duan Yu | 19 | M | Miejue Shitai | 77 | F |
| Xu Zhu | 21 | M | Lin Chaoying | 26 | F |
| Xu Zhu | 21 | M | Miejue Shitai | 77 | F |
| Lin Chong | 25 | M | Lin Chaoying | 26 | F |
| Lin Chong | 25 | M | Miejue Shitai | 77 | F |
| Hua Rong | 23 | M | Lin Chaoying | 26 | F |
| Hua Rong | 23 | M | Miejue Shitai | 77 | F |
| Xue Baochai | 18 | F | Zhang Sanfeng | 94 | M |
| Xue Baochai | 18 | F | Song Jiang | 45 | M |
| Diao Chan | 19 | F | Zhang Sanfeng | 94 | M |
| Diao Chan | 19 | F | Song Jiang | 45 | M |
| Huang Yueying | 22 | F | Zhang Sanfeng | 94 | M |
| Huang Yueying | 22 | F | Song Jiang | 45 | M |
| Xiao Qiao | 20 | F | Zhang Sanfeng | 94 | M |
| Xiao Qiao | 20 | F | Song Jiang | 45 | M |
| Ma Chao | 23 | M | Lin Chaoying | 26 | F |
| Ma Chao | 23 | M | Miejue Shitai | 77 | F |
| Xu Xian | 27 | M | Lin Chaoying | 26 | F |
| Xu Xian | 27 | M | Miejue Shitai | 77 | F |
| Sun Dasheng | 77 | M | Lin Chaoying | 26 | F |
| Sun Dasheng | 77 | M | Miejue Shitai | 77 | F |
+---------------+--------------+--------------+---------------+--------------+--------------+
50 rows in set (0.00 sec)mysql> select stuid,s.name,tid,t.name from students s,teachers t where s.teacherid=t.tid;
+-------+-------------+-----+---------------+
| stuid | name | tid | name |
+-------+-------------+-----+---------------+
| 1 | Shi Zhongyu | 3 | Miejue Shitai |
| 4 | Ding Dian | 4 | Lin Chaoying |
| 5 | Yu Yutong | 1 | Song Jiang |
+-------+-------------+-----+---------------+
3 rows in set (0.00 sec)#内连接后过滤数据
#过滤出s.teacherid=t.tid并且学生年龄大于30的
mysql> select * from students s inner join teachers t on s.teacherid=t.tid and s.age > 30;
+-------+-----------+-----+--------+---------+-----------+-----+--------------+-----+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+-----------+-----+--------+---------+-----------+-----+--------------+-----+--------+
| 4 | Ding Dian | 32 | M | 4 | 4 | 4 | Lin Chaoying | 26 | F |
+-------+-----------+-----+--------+---------+-----------+-----+--------------+-----+--------+
1 row in set (0.00 sec)
自然连接
- 当源表和目标表共享相同名称的列时,就可以在它们之间执行自然连接,而无需指定连接列。
- 在使用纯自然连接时,如没有相同的列时,会产生交叉连接(笛卡尔乘积)
- 语法:(SQL:1999)SELECT table1.column, table2.column FROM table1 NATURAL JOIN table2;
范例:
mysql> create table t1 ( id int,name char(20));
mysql> create table t2 ( id int,title char(20));
mysql> insert t1 values(1,'mage'),(2,'wang'),(3,'zhang');
mysql> insert t2 values(1,'ceo'),(2,'cto');mysql> select * from t1;
+------+-------+
| id | name |
+------+-------+
| 1 | mage |
| 2 | wang |
| 3 | zhang |
+------+-------+
3 rows in set (0.00 sec)mysql> select * from t2;
+------+-------+
| id | title |
+------+-------+
| 1 | ceo |
| 2 | cto |
+------+-------+
2 rows in set (0.00 sec)#自然连接是一种根据表中的共同列自动匹配记录的操作。它会查找两个表中具有相同列名且相等值的记录,并返回这些记录的组合。
mysql> select * from t1 NATURAL JOIN t2;
+------+------+-------+
| id | name | title |
+------+------+-------+
| 1 | mage | ceo |
| 2 | wang | cto |
+------+------+-------+
2 rows in set (0.00 sec)mysql> select t1.name,t2.title from t1 NATURAL JOIN t2;
+------+-------+
| name | title |
+------+-------+
| mage | ceo |
| wang | cto |
+------+-------+
2 rows in set (0.00 sec)
左和右外连接
左连接: 以左表为主根据条件查询右表数据﹐如果根据条件查询右表数据不存在使用null值填充
右连接: 以右表为主根据条件查询左表数据﹐如果根据条件查询左表数据不存在使用null值填充
范例:左,右外连接
#左外连接
mysql> select s.stuid,s.name,s.age,s.teacherid,t.tid,t.name,t.age from students as s left outer join teachers as t on s.teacherid=t.tid;
+-------+---------------+-----+-----------+------+---------------+------+
| stuid | name | age | teacherid | tid | name | age |
+-------+---------------+-----+-----------+------+---------------+------+
| 1 | Shi Zhongyu | 22 | 3 | 3 | Miejue Shitai | 77 |
| 2 | Shi Potian | 22 | 7 | NULL | NULL | NULL |
| 3 | Xie Yanke | 53 | 16 | NULL | NULL | NULL |
| 4 | Ding Dian | 32 | 4 | 4 | Lin Chaoying | 26 |
| 5 | Yu Yutong | 26 | 1 | 1 | Song Jiang | 45 |
| 6 | Shi Qing | 46 | NULL | NULL | NULL | NULL |
| 7 | Xi Ren | 19 | NULL | NULL | NULL | NULL |
| 8 | Lin Daiyu | 17 | NULL | NULL | NULL | NULL |
| 9 | Ren Yingying | 20 | NULL | NULL | NULL | NULL |
| 10 | Yue Lingshan | 19 | NULL | NULL | NULL | NULL |
| 11 | Yuan Chengzhi | 23 | NULL | NULL | NULL | NULL |
| 12 | Wen Qingqing | 19 | NULL | NULL | NULL | NULL |
| 13 | Tian Boguang | 33 | NULL | NULL | NULL | NULL |
| 14 | Lu Wushuang | 17 | NULL | NULL | NULL | NULL |
| 15 | Duan Yu | 19 | NULL | NULL | NULL | NULL |
| 16 | Xu Zhu | 21 | NULL | NULL | NULL | NULL |
| 17 | Lin Chong | 25 | NULL | NULL | NULL | NULL |
| 18 | Hua Rong | 23 | NULL | NULL | NULL | NULL |
| 19 | Xue Baochai | 18 | NULL | NULL | NULL | NULL |
| 20 | Diao Chan | 19 | NULL | NULL | NULL | NULL |
| 21 | Huang Yueying | 22 | NULL | NULL | NULL | NULL |
| 22 | Xiao Qiao | 20 | NULL | NULL | NULL | NULL |
| 23 | Ma Chao | 23 | NULL | NULL | NULL | NULL |
| 24 | Xu Xian | 27 | NULL | NULL | NULL | NULL |
| 25 | Sun Dasheng | 77 | NULL | NULL | NULL | NULL |
+-------+---------------+-----+-----------+------+---------------+------+
25 rows in set (0.00 sec)#左外连接扩展,过滤出t.tid为空的记录
mysql> select * from students s left outer join teachers t on s.teacherid=t.tid where t.tid is null;
+-------+---------------+-----+--------+---------+-----------+------+------+------+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+---------------+-----+--------+---------+-----------+------+------+------+--------+
| 2 | Shi Potian | 22 | M | 1 | 7 | NULL | NULL | NULL | NULL |
| 3 | Xie Yanke | 53 | M | 2 | 16 | NULL | NULL | NULL | NULL |
| 6 | Shi Qing | 46 | M | 5 | NULL | NULL | NULL | NULL | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | NULL | NULL | NULL | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL | NULL | NULL | NULL | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL | NULL | NULL | NULL | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL | NULL | NULL | NULL | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL | NULL | NULL | NULL | NULL |
| 25 | Sun Dasheng | 77 | M | NULL | NULL | NULL | NULL | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+------+------+------+--------+
22 rows in set (0.00 sec)#多个条件的左外连接
#条件s.teacherid=t.tid and s.teacherid is null互斥,并且没有满足同时成立的情况,因此结果集中会包含所有符合其他部分查询逻辑(例如表间其他列匹配或不匹配)的记录
mysql> select * from students s left outer join teachers t on s.teacherid=t.tid and s.teacherid is null;
+-------+---------------+-----+--------+---------+-----------+------+------+------+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+---------------+-----+--------+---------+-----------+------+------+------+--------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | NULL | NULL | NULL | NULL |
| 2 | Shi Potian | 22 | M | 1 | 7 | NULL | NULL | NULL | NULL |
| 3 | Xie Yanke | 53 | M | 2 | 16 | NULL | NULL | NULL | NULL |
| 4 | Ding Dian | 32 | M | 4 | 4 | NULL | NULL | NULL | NULL |
| 5 | Yu Yutong | 26 | M | 3 | 1 | NULL | NULL | NULL | NULL |
| 6 | Shi Qing | 46 | M | 5 | NULL | NULL | NULL | NULL | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | NULL | NULL | NULL | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL | NULL | NULL | NULL | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL | NULL | NULL | NULL | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL | NULL | NULL | NULL | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL | NULL | NULL | NULL | NULL |
| 25 | Sun Dasheng | 77 | M | NULL | NULL | NULL | NULL | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+------+------+------+--------+
25 rows in set (0.00 sec)#先左外连接,再过滤
mysql> select * from students s left outer join teachers t on s.teacherid=t.tid where s.teacherid is null;
+-------+---------------+-----+--------+---------+-----------+------+------+------+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+---------------+-----+--------+---------+-----------+------+------+------+--------+
| 6 | Shi Qing | 46 | M | 5 | NULL | NULL | NULL | NULL | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | NULL | NULL | NULL | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL | NULL | NULL | NULL | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL | NULL | NULL | NULL | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL | NULL | NULL | NULL | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL | NULL | NULL | NULL | NULL |
| 25 | Sun Dasheng | 77 | M | NULL | NULL | NULL | NULL | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+------+------+------+--------+
20 rows in set (0.00 sec)#右外连接
mysql> select * from students s right outer join teachers t on s.teacherid=t.tid;
+-------+-------------+------+--------+---------+-----------+-----+---------------+-----+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+-------------+------+--------+---------+-----------+-----+---------------+-----+--------+
| 5 | Yu Yutong | 26 | M | 3 | 1 | 1 | Song Jiang | 45 | M |
| NULL | NULL | NULL | NULL | NULL | NULL | 2 | Zhang Sanfeng | 94 | M |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 3 | Miejue Shitai | 77 | F |
| 4 | Ding Dian | 32 | M | 4 | 4 | 4 | Lin Chaoying | 26 | F |
+-------+-------------+------+--------+---------+-----------+-----+---------------+-----+--------+
4 rows in set (0.00 sec)#右外连接的扩展用法,过滤s.teacherid是空值的记录
mysql> select * from students s right outer join teachers t on s.teacherid=t.tid where s.teacherid is null;
+-------+------+------+--------+---------+-----------+-----+---------------+-----+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+------+------+--------+---------+-----------+-----+---------------+-----+--------+
| NULL | NULL | NULL | NULL | NULL | NULL | 2 | Zhang Sanfeng | 94 | M |
+-------+------+------+--------+---------+-----------+-----+---------------+-----+--------+
1 row in set (0.00 sec)
完全外连接
MySQL 不支持完全外连接full outer join语法
范例:完全外连接
#MySQL不支持完全外连接 full outer join,利用以下方式法代替
#通过左外连接和右外连接union联合查询实现完全外连接的效果。
mysql> select * from students left join teachers on students.teacherid=teachers.tid -> union-> select * from students right join teachers on students.teacherid=teachers.tid;mysql> select s.stuid,s.name,s.age,t.tid,t.name,t.age from students as s left join teachers as t on s.teacherid=t.tid-> union -> select s.stuid,s.name,s.age,t.tid,t.name,t.age from students as s right join teachers as t on s.teacherid=t.tid;
+-------+---------------+------+------+---------------+------+
| stuid | name | age | tid | name | age |
+-------+---------------+------+------+---------------+------+
| 1 | Shi Zhongyu | 22 | 3 | Miejue Shitai | 77 |
| 2 | Shi Potian | 22 | NULL | NULL | NULL |
| 3 | Xie Yanke | 53 | NULL | NULL | NULL |
| 4 | Ding Dian | 32 | 4 | Lin Chaoying | 26 |
| 5 | Yu Yutong | 26 | 1 | Song Jiang | 45 |
| 6 | Shi Qing | 46 | NULL | NULL | NULL |
| 7 | Xi Ren | 19 | NULL | NULL | NULL |
| 8 | Lin Daiyu | 17 | NULL | NULL | NULL |
| 9 | Ren Yingying | 20 | NULL | NULL | NULL |
| 10 | Yue Lingshan | 19 | NULL | NULL | NULL |
| 11 | Yuan Chengzhi | 23 | NULL | NULL | NULL |
| 12 | Wen Qingqing | 19 | NULL | NULL | NULL |
| 13 | Tian Boguang | 33 | NULL | NULL | NULL |
| 14 | Lu Wushuang | 17 | NULL | NULL | NULL |
| 15 | Duan Yu | 19 | NULL | NULL | NULL |
| 16 | Xu Zhu | 21 | NULL | NULL | NULL |
| 17 | Lin Chong | 25 | NULL | NULL | NULL |
| 18 | Hua Rong | 23 | NULL | NULL | NULL |
| 19 | Xue Baochai | 18 | NULL | NULL | NULL |
| 20 | Diao Chan | 19 | NULL | NULL | NULL |
| 21 | Huang Yueying | 22 | NULL | NULL | NULL |
| 22 | Xiao Qiao | 20 | NULL | NULL | NULL |
| 23 | Ma Chao | 23 | NULL | NULL | NULL |
| 24 | Xu Xian | 27 | NULL | NULL | NULL |
| 25 | Sun Dasheng | 77 | NULL | NULL | NULL |
| NULL | NULL | NULL | 2 | Zhang Sanfeng | 94 |
+-------+---------------+------+------+---------------+------+
26 rows in set (0.00 sec)#完全外连接的扩展示例
#完全外连接不含交集
mysql> select * from students s left outer join teachers t on s.teacherid=t.tid where t.tid is null union select * from students s right outer join teachers t on s.teacherid=t.tid where s.teacherid is null;
+-------+---------------+------+--------+---------+-----------+------+---------------+------+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+---------------+------+--------+---------+-----------+------+---------------+------+--------+
| 2 | Shi Potian | 22 | M | 1 | 7 | NULL | NULL | NULL | NULL |
| 3 | Xie Yanke | 53 | M | 2 | 16 | NULL | NULL | NULL | NULL |
| 6 | Shi Qing | 46 | M | 5 | NULL | NULL | NULL | NULL | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | NULL | NULL | NULL | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL | NULL | NULL | NULL | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL | NULL | NULL | NULL | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL | NULL | NULL | NULL | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL | NULL | NULL | NULL | NULL |
| 25 | Sun Dasheng | 77 | M | NULL | NULL | NULL | NULL | NULL | NULL |
| NULL | NULL | NULL | NULL | NULL | NULL | 2 | Zhang Sanfeng | 94 | M |
+-------+---------------+------+--------+---------+-----------+------+---------------+------+--------+
23 rows in set (0.00 sec)mysql> select * from (select s.stuid,s.name s_name,s.teacherid,t.tid,t.name t_name from students s left outer join teachers t on s.teacherid=t.tid union select s.stuid,s.name,s.teacherid,t.tid,t.name from students s right outer join teachers t on s.teacherid=t.tid) as a where a.teacherid is null or a.tid is null;
+-------+---------------+-----------+------+---------------+
| stuid | s_name | teacherid | tid | t_name |
+-------+---------------+-----------+------+---------------+
| 2 | Shi Potian | 7 | NULL | NULL |
| 3 | Xie Yanke | 16 | NULL | NULL |
| 6 | Shi Qing | NULL | NULL | NULL |
| 7 | Xi Ren | NULL | NULL | NULL |
| 8 | Lin Daiyu | NULL | NULL | NULL |
| 9 | Ren Yingying | NULL | NULL | NULL |
| 10 | Yue Lingshan | NULL | NULL | NULL |
| 11 | Yuan Chengzhi | NULL | NULL | NULL |
| 12 | Wen Qingqing | NULL | NULL | NULL |
| 13 | Tian Boguang | NULL | NULL | NULL |
| 14 | Lu Wushuang | NULL | NULL | NULL |
| 15 | Duan Yu | NULL | NULL | NULL |
| 16 | Xu Zhu | NULL | NULL | NULL |
| 17 | Lin Chong | NULL | NULL | NULL |
| 18 | Hua Rong | NULL | NULL | NULL |
| 19 | Xue Baochai | NULL | NULL | NULL |
| 20 | Diao Chan | NULL | NULL | NULL |
| 21 | Huang Yueying | NULL | NULL | NULL |
| 22 | Xiao Qiao | NULL | NULL | NULL |
| 23 | Ma Chao | NULL | NULL | NULL |
| 24 | Xu Xian | NULL | NULL | NULL |
| 25 | Sun Dasheng | NULL | NULL | NULL |
| NULL | NULL | NULL | 2 | Zhang Sanfeng |
+-------+---------------+-----------+------+---------------+
23 rows in set (0.00 sec)
自连接
自连接, 即表自身连接自身
范例:自连接
#自连接
mysql> select * from emp;
+----+----------+----------+
| id | name | leaderid |
+----+----------+----------+
| 1 | mage | NULL |
| 2 | zhangsir | 1 |
| 3 | wang | 2 |
| 4 | zhang | 3 |
+----+----------+----------+
4 rows in set (0.00 sec)mysql> select e.name emp_name,l.name leader_name from emp as e left join emp as l on e.leaderid=l.id;;
+----------+-------------+
| emp_name | leader_name |
+----------+-------------+
| mage | NULL |
| zhangsir | mage |
| wang | zhangsir |
| zhang | wang |
+----------+-------------+
4 rows in set (0.00 sec)#ifnull函数对l.name中的空值替换为无上级
mysql> select e.name emp_name,ifnull(l.name,'无上级') leader_name from emp as e left join emp as l onn e.leaderid=l.id;
+----------+-------------+
| emp_name | leader_name |
+----------+-------------+
| mage | 无上级 |
| zhangsir | mage |
| wang | zhangsir |
| zhang | wang |
+----------+-------------+
4 rows in set (0.00 sec)
范例:三表连接
#三张表连接示例
#通过将学生表 (students) 的 "stuid" 列与成绩表 (scores) 的 "stuid" 列以及score表的 "courseid" 列与课程表 (courses) 的 "CourseID" 列进行匹配,可以获取到每位学生所修读过的每门课程以及他们在各门课上获得的分数。
mysql> select name,course,score from students st inner join scores sc on st.stuid=sc.stuid inner join courses co on sc.courseid=co.CourseID;
+-------------+----------------+-------+
| name | course | score |
+-------------+----------------+-------+
| Shi Zhongyu | Kuihua Baodian | 77 |
| Shi Zhongyu | Weituo Zhang | 93 |
| Shi Potian | Kuihua Baodian | 47 |
| Shi Potian | Daiyu Zanghua | 97 |
| Xie Yanke | Kuihua Baodian | 88 |
| Xie Yanke | Weituo Zhang | 75 |
| Ding Dian | Daiyu Zanghua | 71 |
| Ding Dian | Kuihua Baodian | 89 |
| Yu Yutong | Hamo Gong | 39 |
| Yu Yutong | Dagou Bangfa | 63 |
| Shi Qing | Hamo Gong | 96 |
| Xi Ren | Hamo Gong | 86 |
| Xi Ren | Dagou Bangfa | 83 |
| Lin Daiyu | Taiji Quan | 57 |
| Lin Daiyu | Jinshe Jianfa | 93 |
+-------------+----------------+-------+
15 rows in set (0.00 sec)mysql> select st.name,co.Course,sc.score from courses co inner join scores sc on co.courseid=sc.courseid inner join students st on sc.stuid=st.stuid;
+-------------+----------------+-------+
| name | Course | score |
+-------------+----------------+-------+
| Shi Zhongyu | Kuihua Baodian | 77 |
| Shi Zhongyu | Weituo Zhang | 93 |
| Shi Potian | Kuihua Baodian | 47 |
| Shi Potian | Daiyu Zanghua | 97 |
| Xie Yanke | Kuihua Baodian | 88 |
| Xie Yanke | Weituo Zhang | 75 |
| Ding Dian | Daiyu Zanghua | 71 |
| Ding Dian | Kuihua Baodian | 89 |
| Yu Yutong | Hamo Gong | 39 |
| Yu Yutong | Dagou Bangfa | 63 |
| Shi Qing | Hamo Gong | 96 |
| Xi Ren | Hamo Gong | 86 |
| Xi Ren | Dagou Bangfa | 83 |
| Lin Daiyu | Taiji Quan | 57 |
| Lin Daiyu | Jinshe Jianfa | 93 |
+-------------+----------------+-------+
15 rows in set (0.00 sec)
SELECT 语句处理的顺序
查询执行路径中的组件:查询缓存、解析器、预处理器、优化器、查询执行引擎、存储引擎
SELECT语句的执行流程:
FROM Clause --> WHERE Clause --> GROUP BY --> HAVING Clause -->SELECT --> ORDER BY --> LIMIT
练习
导入hellodb.sql生成数据库
- 在students表中,查询年龄大于25岁,且为男性的同学的名字和年龄
select name,age from students where age > 25 and gender='M';
- 以ClassID为分组依据,显示每组的平均年龄
select classid,avg(age) from students group by classid;
- 显示第2题中平均年龄大于30的分组及平均年龄
select classid,avg(age) from students group by classid having avg(age)>30;
- 显示以L开头的名字的同学的信息
select * from students where name LIKE 'L%';
- 显示TeacherID非空的同学的相关信息
select * from students where teacherid is not null;
- 以年龄排序后,显示年龄最大的前10位同学的信息
select * from students order by age desc limit 10;
- 查询年龄大于等于20岁,小于等于25岁的同学的信息
select * from students where age >= 20 and age <= 25;
- 以ClassID分组,显示每班的同学的人数
select classid,count(classid) from students group by classid;
- 以Gender分组,显示其年龄之和
select gender,sum(age) from students group by gender;
- 以ClassID分组,显示其平均年龄大于25的班级
select classid,avg(age) from students group by classid having avg(age) > 25;
- 以Gender分组,显示各组中年龄大于25的学员的年龄之和
select gender,sum(age) from students where age > 25 group by gender;
- 显示前5位同学的姓名、课程及成绩
select name,course,score from students st inner join scores sc on st.stuid=sc.stuid inner join courses co on sc.courseid=co.CourseID limit 5;
- 显示其成绩高于80的同学的名称及课程
select name,course,score from students st inner join scores sc on st.stuid=sc.stuid inner join courses co on sc.courseid=co.CourseID where score > 80;
- 取每位同学各门课的平均成绩,显示成绩前三名的同学的姓名和平均成绩
select st.name, avg(sc.score) as avg_score from students st join scores sc on st.stuid = sc.stuid group by st.stuid order by avg_score
desc limit 3;
- 显示每门课程课程名称及学习了这门课的同学的个数
SELECT c.Course, COUNT(DISTINCT s.StuID) AS StudentCount FROM courses c LEFT JOIN scores s ON c.CourseID = s.CourseID GROUP BY c.CourseID;
- 显示其年龄大于平均年龄的同学的名字
SELECT Name FROM students WHERE Age > (SELECT AVG(Age) FROM students);
- 显示其学习的课程为第1、2,4或第7门课的同学的名字
SELECT DISTINCT s.Name FROM students s JOIN scores sc ON s.StuID = sc.StuID WHERE sc.CourseID IN (1, 2, 4, 7);
- 显示其成员数最少为3个的班级的同学中年龄大于同班同学平均年龄的同学
SELECT s.Name FROM students s JOIN (SELECT classid, AVG(age) AS avg_age, COUNT(*) AS class_count FROM students GROUP BY classid HAVING class_count >= 3) AS class_info ON s.classid = class_info.classid WHERE s.age > class_info.avg_age;
- 统计各班级中年龄大于全校同学平均年龄的同学
SELECT classid, COUNT(*) AS student_count FROM students WHERE age > (SELECT AVG(age) FROM students) GROUP BY classid;