200字
SQL语言和MySQL的字符集和排序规则及数据类型
2026-02-26
2026-02-26

SQL语言

关系数据库的常见组件

  • 数据库:database 表的集合,物理上表现为一个目录
  • 表:table,行:row 列:column
  • 索引:index
  • 视图:view,虚拟的表
  • 存储过程:procedure
  • 存储函数:function
  • 触发器:trigger
  • 事件调度器:event scheduler,任务计划
  • 用户:user
  • 权限:privilege

SQL语言规范

在数据库系统中,SQL 语句不区分大小写,建议用大写
SQL语句可单行或多行书写,默认以 " ; " 结尾
关键词不能跨多行或简写
用空格和TAB 缩进来提高语句的可读性
子句通常位于独立行,便于编辑,提高可读性

注释:

  • SQL标准:
#单行注释,注意有空格
-- 注释内容
#多行注释
/*注释内容
注释内容
注释内容*/
  • MySQL注释:
# 注释内容

数据库对象和命名

数据库的组件(对象):

数据库、表、索引、视图、用户、存储过程、函数、触发器、事件调度器等

命名规则:

  • 必须以字母开头,后续可以包括字母,数字和三个特殊字符(# _ $)
  • 不要使用MySQL的保留字

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

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帮助

MariaDB [mysql]> help contents

MySQL [(none)]> help Data Types

MySQL [(none)]> help bit

查看SQL帮助

mysql> HELP KEYWORD

字符集和排序

早期MySQL版本默认为 latin1,从MySQL8.0开始默认字符集已经为 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=utf8mb4

范例:字符集和相关文件

mysql> SHOW CHARACTER SET;

[root@centos8 ~]#ll /usr/share/mysql/charsets/

范例:MySQL 8.0 默认的字符集和排序规则

11:18:28(root@localhost) [(none)]> SHOW VARIABLES LIKE 'collation%';
+----------------------+--------------------+
| Variable_name        | Value              |
+----------------------+--------------------+
| collation_connection | utf8mb4_0900_ai_ci |
| collation_database   | utf8mb4_0900_ai_ci |
| collation_server     | utf8mb4_0900_ai_ci |
+----------------------+--------------------+
3 rows in set (0.00 sec)

11:20:16(root@localhost) [(none)]> show variables like 'character%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8mb4                    |
| character_set_connection | utf8mb4                    |
| character_set_database   | utf8mb4                    |
| character_set_filesystem | binary                     |
| character_set_results    | utf8mb4                    |
| character_set_server     | utf8mb4                    |
| character_set_system     | utf8mb3                    |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

管理数据库

创建数据库

CREATE DATABASE|SCHEMA [IF NOT EXISTS] 'DB_NAME'
CHARACTER SET 'character set name'
COLLATE 'collate name';

示例:

11:22:09(root@localhost) [(none)]> create database db1
    -> ;
Query OK, 1 row affected (0.02 sec)



11:30:05(root@localhost) [(none)]> show create database db1;\G
+----------+-------------------------------------------------------------------------------------------------------------------------------+
| Database | Create Database                                                                                                               |
+----------+-------------------------------------------------------------------------------------------------------------------------------+
| db1      | CREATE DATABASE `db1` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */ |
+----------+-------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

范例:指定字符集创建新数据库

11:30:32(root@localhost) [(none)]> create database IF NOT EXISTS db2 CHARACTER SET 'utf8';
Query OK, 1 row affected, 1 warning (0.02 sec)

范例: 手动创建数据库

mysql> create database zabbix character set utf8 collate utf8_bin;

范例: 以容器方式启动并创建数据库

[root@centos8 ~]#docker run --name mysql-server -t \
		-e MYSQL_DATABASE="zabbix" \
		-e MYSQL_USER="zabbix" \
		-e MYSQL_PASSWORD="zabbix_pwd" \
		-e MYSQL_ROOT_PASSWORD="root_pwd" \
		-d mysql:5.7 \
		--character-set-server=utf8 --collation-server=utf8_bin
[root@centos8 ~]#docker run -d -p 3306:3306 --name mysql \
		-e MYSQL_ROOT_PASSWORD=123456 \
		-e MYSQL_DATABASE=jumpserver
		-e MYSQL_USER=jumpserver
		-e MYSQL_PASSWORD=123456
		-v /data/mysql:/var/lib/mysql
		-v
/etc/mysql/mysql.conf.d/mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf \
		-v /etc/mysql/conf.d/mysql.cnf:/etc/mysql/conf.d/mysql.cnf
mysql:5.7.30

修改数据库

ALTER DATABASE DB_NAME character set utf8;

范例:

MariaDB [(none)]> ALTER DATABASE db1 character set utf8 COLLATE utf8_bin;
Query OK, 1 row affected (0.001 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.000 sec)
[root@centos8 ~]#cat /var/lib/mysql/db1/db.opt
default-character-set=utf8
default-collation=utf8_general_ci

删除数据库

DROP DATABASE|SCHEMA [IF EXISTS] 'DB_NAME';
11:31:25(root@localhost) [(none)]> drop database db1;
Query OK, 0 rows affected (0.03 sec)

[root@mysql ~]# ls /var/lib/mysql/
'#ib_16384_0.dblwr'   binlog.000001   binlog.000006   ca.pem            ibdata1     performance_schema   sys
'#ib_16384_1.dblwr'   binlog.000002   binlog.000007   client-cert.pem   ibtmp1      private_key.pem      undo_001
'#innodb_redo'        binlog.000003   binlog.000008   client-key.pem    mysql       public_key.pem       undo_002
'#innodb_temp'        binlog.000004   binlog.index    debian-5.7.flag   mysql.ibd   server-cert.pem
 auto.cnf             binlog.000005   ca-key.pem      ib_buffer_pool    mysql.pid   server-key.pem

查看数据库列表

SHOW DATABASES;

范例:

12:44:52(root@localhost) [(none)]>  show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

数据类型

数据类型:

  • 数据长什么样
  • 数据需要多少空间来存放

数据类型:

  • 系统内置数据类型
  • 用户定义数据类型

MySQL支持多种内置数据类型

  • 数值类型
  • 日期/时间类型
  • 字符串(字符)类型

数据类型参考链接

https://dev.mysql.com/doc/refman/8.0/en/data-types.html

选择正确的数据类型对于获得高性能至关重要,三大原则:

更小的通常更好,尽量使用可正确存储数据的最小数据类型

简单就好,简单数据类型的操作通常需要更少的CPU周期

尽量避免NULL,包含为NULL的列,对MySQL更难优化

整数型

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后,则最大值翻倍
如:tinyint unsigned的取值范围为(0~255)

int(m)里的m是表示SELECT查询结果集中的显示宽度,并不影响实际的取值范围,规定了MySQL的一些交互工具(例如MySQL命令行客户端)用来显示字符的个数。对于存储和计算来说,Int(1)和Int(20)是相同的

BOOL,BOOLEAN:布尔型,是TINYINT(1)的同义词。zero值被视为假,非zero值视为真

浮点型(float和double)

浮点型为近似值,不精确,分为单精度和双精度

float(m,d) 单精度浮点型 8位精度(4字节) m总个数,d小数位, 注意: 小数点不占用总个数
double(m,d) 双精度浮点型16位精度(8字节) m总个数,d小数位, 注意: 小数点不占用总个数

示例:

设一个字段定义为float(6,3),如果插入一个数123.45678,实际数据库里存的是123.457,但总个数还以实际为准,即6位 float(总位数,小数占总位数多少)

定点数

在数据库中存放的是精确值,存为十进制

格式 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

字符串(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

价值CHAR(4)需储存VARCHAR(4)需储存
''' '4字节''1 字节
'ab''ab '4字节'ab'3 字节
'abcd''abcd'4字节'abcd'5字节
'abcdefgh''abcd'4字节'abcd'5字节

char(n) 若存入字符数小于n,则以空格补于其后,查询之时再将空格去掉,所以char类型存储的字符串末尾不能有空格(可能被误删),varchar不限于此

char(n) 固定长度,char(4)不管是存入几个字符,都将占用4个字节,varchar是存入的实际字符数+1个字节(n< n>255),所以varchar(4),存入3个字符将占用4个字节

char类型的字符串检索速度要比varchar类型的快

varchar 和 text:

varchar可指定n,text不能指定,内部存储varchar是存入的实际字符数+1个字节(n< n>255),text是实际字符数+2个字节。

text类型不能有默认值

varchar可直接创建索引,text创建索引要指定前多少个字符。varchar查询速度快于text

二进制数据BLOB

BLOB和text存储方式不同,TEXT以文本方式存储,英文存储区分大小写,而Blob以二进制方式存储,不分大小写

BLOB存储的数据只能整体读出

TEXT可以指定字符集,BLOB不用指定字符集

日期时间类型

date 日期 '2008-12-2'
time 时间 '12:25:36'
datetime 日期时间 '2008-12-2 22:06:44'
timestamp 自动存储记录修改时间
YEAR(2), YEAR(4):年份
timestamp 此字段里的时间数据会随其他字段修改的时候自动刷新 这个数据类型的字段可以存放 这条记录最后被修改的时间

修饰符

适用所有类型的修饰符:

NULL 数据列可包含NULL值,默认值
NOT NULL 数据列不允许包含NULL值,相当于网站注册表中的 * 为必填选项
DEFAULT 默认值
PRIMARY KEY 主键,所有记录中此字段的值不能重复,且不能为NULL
UNIQUE KEY 唯一键,所有记录中此字段的值不能重复,但可以为NULL
CHARACTER SET name 指定一个字符集

适用数值型的修饰符:

AUTO_INCREMENT 自动递增,适用于整数类型, 必须作用于某个 key 的字段,比如primary key
UNSIGNED 无符号

范例:关于AUTO_INCREMENT

13:53:11(root@localhost) [(none)]> SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 1     |
| auto_increment_offset    | 1     |
+--------------------------+-------+
2 rows in set (0.00 sec)

# auto_increment_offset 定义初始值
# auto_increment_increment 定义步进

范例:

13:53:17(root@localhost) [(none)]> create database test;
Query OK, 1 row affected (0.02 sec)

13:54:11(root@localhost) [(none)]> create table test.t1(id int unsigned auto_increment primary key);
Query OK, 0 rows affected (0.07 sec)

13:54:30(root@localhost) [(none)]> 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: 0
 Auto_increment: NULL
    Create_time: 2026-02-26 13:54:30
    Update_time: NULL
     Check_time: NULL
      Collation: utf8mb4_0900_ai_ci
       Checksum: NULL
 Create_options: 
        Comment: 
1 row in set (0.02 sec)

13:55:55(root@localhost) [(none)]> insert into test.t1 values(null);
Query OK, 1 row affected (0.02 sec)

13:56:03(root@localhost) [(none)]> insert into test.t1 values(null);
Query OK, 1 row affected (0.02 sec)

13:56:17(root@localhost) [(none)]> select * from test.t1;
+----+
| id |
+----+
|  1 |
|  2 |
+----+
2 rows in set (0.00 sec)


#上面表的数据类型无法存放所有数据,修改过数据类型实现
13:59:34(root@localhost) [(none)]> alter table test.t1 modify id bigint auto_increment ;


13:59:34(root@localhost) [(none)]> desc test.t1
    -> ;
+-------+--------+------+-----+---------+----------------+
| Field | Type   | Null | Key | Default | Extra          |
+-------+--------+------+-----+---------+----------------+
| id    | bigint | NO   | PRI | NULL    | auto_increment |
+-------+--------+------+-----+---------+----------------+
1 row in set (0.00 sec)

14:00:37(root@localhost) [(none)]> insert test.t1 values(null);
Query OK, 1 row affected (0.02 sec)

14:01:01(root@localhost) [(none)]> select * from test.t1;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
+----+
3 rows in set (0.00 sec)

DDL语句

表:二维关系

设计表:遵循规范

定义:字段,索引

  • 字段:字段名,字段数据类型,修饰符
  • 约束,索引:应该创建在经常用作查询条件的字段上

创建表

参考文档:

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是指表类型,也即在表创建时指明其使用的存储引擎
  • 同一库中不同表可以使用不同的存储引擎
  • 同一个库中表建议要使用同一种存储引擎类型

范例:创建表

CREATE TABLE student (
id int UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
age tinyint UNSIGNED,
#height DECIMAL(5,2),
gender ENUM('M','F') default 'M'
)ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
#id字段以10初始值

DESC student;
14:58:18(root@localhost) [test]> DESC student;
+--------+------------------+------+-----+---------+----------------+
| Field  | Type             | Null | Key | Default | Extra          |
+--------+------------------+------+-----+---------+----------------+
| id     | int unsigned     | NO   | PRI | NULL    | auto_increment |
| name   | varchar(20)      | NO   |     | NULL    |                |
| age    | tinyint unsigned | YES  |     | NULL    |                |
| gender | enum('M','F')    | YES  |     | M       |                |
+--------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
insert student (name,age)values('xiaoming',20);
Query OK, 1 row affected (0.002 sec)

select * from student;
+----+----------+------+--------+
| id | name     | age  | gender |
+----+----------+------+--------+
| 10 | xiaoming |   20 | M      |
+----+----------+------+--------+
1 row in set (0.00 sec)

15:02:22(root@localhost) [test]> insert student (name,age,gender)values('xiaohong',18,'f');
Query OK, 1 row affected (0.02 sec)

15:08:35(root@localhost) [test]> select * from student;
+----+----------+------+--------+
| id | name     | age  | gender |
+----+----------+------+--------+
| 10 | xiaoming |   20 | M      |
| 11 | xiaohong |   18 | F      |
+----+----------+------+--------+
2 rows in set (0.00 sec)


CREATE TABLE employee (
id int UNSIGNED NOT NULL ,
name VARCHAR(20) NOT NULL,
age tinyint UNSIGNED,
PRIMARY KEY(id,name))

范例:auto_increment 属性

SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
+--------------------------+-------+
2 rows in set (0.001 sec)

SET @@auto_increment_increment=10;
Query OK, 0 rows affected (0.001 sec)

SET @@auto_increment_offset=3;
Query OK, 0 rows affected (0.000 sec)

SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 10 |
| auto_increment_offset | 3 |
+--------------------------+-------+
2 rows in set (0.001 sec)

CREATE TABLE autoinc1 (col INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
Query OK, 0 rows affected (0.004 sec)

INSERT INTO autoinc1 VALUES (NULL), (NULL), (NULL), (NULL);
Query OK, 4 rows affected (0.001 sec)
Records: 4 Duplicates: 0 Warnings: 0

SELECT col FROM autoinc1;
+-----+
| col |
+-----+
| 3 |
| 13 |
| 23 |
| 33 |
+-----+

范例:时间类型

create table testdate (id int auto_increment primary key,date
timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL);
insert testdate ()values()()();
select * from testdate;
+----+---------------------+
| id | date |
+----+---------------------+
| 1 | 2020-09-23 08:41:43 |
| 2 | 2020-09-23 08:41:43 |
| 3 | 2020-09-23 08:41:43 |
+----+---------------------+
3 row in set (0.000 sec)

(2)通过查询现存表创建;新表会被直接插入查询而来的数据

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)]
[table_options]
[partition_options] select_statement

范例:

create table user select user,host,password from mysql.user;
Query OK, 4 rows affected (0.008 sec)
Records: 4 Duplicates: 0 Warnings: 0

show tables;
+---------------+
| Tables_in_db1 |
+---------------+
| student |
| user |
+---------------+
2 rows in set (0.000 sec)

desc user;
+----------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+----------+------+-----+---------+-------+
| user | char(80) | NO | | | |
| host | char(60) | NO | | | |
| password | char(41) | NO | | | |
+----------+----------+------+-----+---------+-------+

(3) 通过复制现存的表的表结构创建,但不复制数据

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name { LIKE old_tbl_name | (LIKE old_tbl_name) }

范例:

esc 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.001 sec)

create table teacher like student;
Query OK, 0 rows affected (0.006 sec)

desc teacher;
+--------+---------------------+------+-----+---------+----------------+
| 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.001 sec)

范例: 创建外键表

create table school ( id int primary key auto_increment,name
varchar(10));


create table teacher(id int primary key auto_increment,name varchar(10),school_id int,foreign key(school_id) references school(id));

表查看

查看表:

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;

查看库中所有表状态

SHOW TABLE STATUS FROM db_name

修改表删除表

修改表

ALTER TABLE 'tbl_name'
#字段:
#添加字段:add
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 name varchar(20) character set utf8;

#添加字段
ALTER TABLE students ADD gender ENUM('m','f');
alter table student modify is_del bool default false;

#修改字段名和类型
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 <外键名>;

DML 语句

DML: INSERT, DELETE, UPDATE

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_name
		SET col_name={expr | DEFAULT}, ...
		[ ON DUPLICATE KEY UPDATE
		col_name=expr
		[, col_name=expr] ... ]
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
		[INTO] tbl_name [(col_name,...)]
		SELECT ...
		[ ON DUPLICATE KEY UPDATE
		col_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.01 sec)
mysql> select * from student;
+----+------+------+--------+
| id | name | age | gender |
+----+------+------+--------+
| 1 | wang | 18 | M |
+----+------+------+--------+
1 row in set (0.00 sec)

范例: 部分列插入

ysql> insert student(name,age)values('zhang',20);
Query OK, 1 row affected (0.01 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.00 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)

UPDATE 语句

语法:

UPDATE [LOW_PRIORITY] [IGNORE] table_reference
    SET 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

DELETE 语句

删除表中数据,但不会自动缩减数据文件的大小。

语法:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
    [WHERE where_condition]
    [ORDER BY ...]
    [LIMIT row_count]
#可先排序再指定删除的行数
DELETE FROM student WHERE id = 10;
DELETE FROM student WHERE age > 20;

注意:一定要有限制条件,否则将清空表中的所有数据

如果想清空表,保留表结构,也可以使用下面语句,此语句会自动缩减数据文件的大小。

TRUNCATE TABLE tbl_name;

缩减表大小

OPTIMIZE TABLE tb_name

范例: 删除数据可以使用逻辑删除,添加一个标识字段实现,删除数据即修改标识字段

mysql> alter table student add is_del bool default false;
#mysql> alter table student add is_del tinyint(1) default 0;
mysql> desc student;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
| is_del | tinyint(1) | YES | | 0 | |
+--------+------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

DQL 语句

单表操作

语法:

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: 读锁,共享锁,同时多个读操作

范例:

MariaDB [hellodb]> select password("hello world") ;
+-------------------------------------------+
| password("hello world") |
+-------------------------------------------+
| *67BECF85308ACF0261750DA1075681EE5C412F05 |
+-------------------------------------------+
1 row in set (0.000 sec)

MariaDB [hellodb]> select md5("hello world") ;
+----------------------------------+
| md5("hello world") |
+----------------------------------+
| 5eb63bbbe01eeed093cb22bb8f5acdc3 |
+----------------------------------+
1 row in set (0.000 sec)

范例:字段别名

MariaDB [hellodb]> select stuid 学员ID,name as 姓名,gender 性别 from students;

范例:简单查询

DESC students;
INSERT INTO students VALUES(1,'tom','m'),(2,'alice','f');
INSERT INTO students(id,name) VALUES(3,'jack'),(4,'allen');
SELECT * FROM students WHERE id < 3;
SELECT * FROM students WHERE gender='m';
SELECT * FROM students WHERE gender IS NULL;
SELECT * FROM students WHERE gender IS NOT NULL;
SELECT * FROM students ORDER BY name DESC LIMIT 2;
SELECT * FROM students ORDER BY name DESC LIMIT 1,2;
SELECT * FROM students WHERE id >=2 and id <=4
SELECT * FROM students WHERE BETWEEN 2 AND 4
SELECT * FROM students WHERE name LIKE 't%'
SELECT * FROM students WHERE name RLIKE '.*[lo].*';
SELECT id stuid,name as stuname FROM students
select * from students where classid in (1,3,5);
select * from students where classid not in (1,3,5);

范例:判断是否为NULL

select * from students where classid is null;

select * from students where classid <=> null

select * from students where classid is not null;

#ifnull函数判断指定的字段是否为空值,如果空值则使用指定默认值
select stuid,name,ifnull(classID,'无班级') from students where classid is null;

范例: 记录去重

select distinct gender from students ;

#将age和gender多个字段重复的记录去重
select distinct age,gender from students;

范例:SQL 注入攻击

create table user (id int auto_increment primary key,name varchar(20),password
varchar(30));
insert into user (name,password) values('admin','123456'),('wu','654321');
select * from user where name='admin' and password='' or '1'='1';
select * from user where name='admin' and password='' or '1=1';
select * from user where name='admin'; -- ' and password='ayaka123';
select * from user where name='admin'; # ' and password='ayaka123';

范例: 分页查询

#只取前3个
mysql> select * from students limit 0,3;
mysql> select * from students limit 3;

# 查询第n页的数据,每页显示m条记录
mysql> select * from students limit (n-1) * m,m;

范例: 聚合函数

mysql> select sum(age)/count(*) from students where gender ='M';
+-------------------+
| sum(age)/count(*) |
+-------------------+
| 33.0000 |
+-------------------+
1 row in set (0.00 sec)

mysql> select sum(age)/count(*) from students where gender ='F';
+-------------------+
| sum(age)/count(*) |
+-------------------+
| 19.0000 |
+-------------------+
1 row 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记录排在最后
select * from students order by -classid desc ;

范例: 分组和排序的次序

#顺序: 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 classidhaving 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' at line 1

#以下顺序会出错,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可以随其它字段的更新自动更新

select * from testdate where date between '2020-06-03 15:21:12' and '2020-06-03 18:27:40';
select * from testdate where date >= '2020-06-03 15:21:12' and date <= '2020-06-03 18:27:40';

#修改其它字段,会自动更新timestamp字段
mysql> update testdate set id=10 where id=1;
mysql> select * from testdate3;
+----+---------------------+
| id | date |
+----+---------------------+
| 2 | 2020-06-03 15:21:12 |
| 3 | 2020-06-03 15:21:14 |
| 4 | 2020-06-03 15:21:17 |
| 5 | 2020-06-03 18:27:39 |
| 6 | 2020-06-03 18:27:44 |
| 10 | 2026-02-26 18:34:51 |
+----+---------------------+
6 rows in set (0.001 sec)

多表查询

多表查询,即查询结果来自于多张表

img

  • 子查询:在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子句,可以是对同一张表,也可以是对不同表,主要有以下四种常见的用法

  1. 用于比较表达式中的子查询;子查询仅能返回单个值
SELECT Name,Age FROM students WHERE Age>(SELECT avg(Age) FROM teachers);
update students set Age=(SELECT avg(Age) FROM teachers) where stuid=25;
  1. 用于IN中的子查询:子查询应该单独查询并返回一个或多个值重新构成列表
SELECT Name,Age FROM students WHERE Age IN (SELECT Age FROM teachers);
  1. 用于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,外查询的这一行数据便可作为外查询的结果行返回,否则不能作为结果

MariaDB [hellodb]> 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 |
+-------+-------------+-----+--------+---------+-----------+

#说明:
1、EXISTS (或 NOT EXISTS) 用在 where之后,且后面紧跟子查询语句(带括号)
2、EXISTS (或 NOT EXISTS) 只关心子查询有没有结果,并不关心子查询的结果具体是什么
3、上述语句把students的记录逐条代入到Exists后面的子查询中,如果子查询结果集不为空,即说
明存在,那么这条students的记录出现在最终结果集,否则被排除

MariaDB [hellodb]> 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 | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
22 rows in set (0.001 sec)
  1. 用于FROM子句中的子查询

使用格式:

SELECT tb_alias.col1,... FROM (SELECT clause) AS tb_alias WHERE Clause;

范例:

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;

范例:子查询

#子查询:select 的执行结果,被其它SQL调用
MariaDB [hellodb]> 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 |
| 25 | Sun Dasheng | 100 |
+-------+--------------+-----+
5 rows in set (0.00 sec)

范例:子查询用于更新表

MariaDB [hellodb]> update teachers set age=(select avg(age) from students) where tid=4;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
MariaDB [hellodb]> 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 | 27 | F |
+-----+---------------+-----+--------+
4 rows in set (0.00 sec)

子查询优化

子查询可以一次性完成很多逻辑上需要多个步骤才能完成的SQL操作。子查询虽然可以使查询语句很灵活,但执行效率不高。执行子查询时,需要为内层查询语句的查询结果建立一个临时表。然后外层查询语句从临时表中查询记录。查询完毕后,再撤销这些临时表。因此,子查询的速度会受到一定的影响。如果查询的数据量比较大,这种影响就会随之增大。
可以使用连接(JOIN)查询来替代子查询。连接查询不需要建立临时表,其速度比子查询要快,如果查询中使用到索引的话,性能会更好。

联合查询

联合查询 Union 实现的条件,多个表的字段数量相同,字段名和数据类型可以不同,但一般数据类型是相同的

SELECT Name,Age FROM students UNION SELECT Name,Age FROM teachers;

范例:联合查询

#多表纵向合并union
MariaDB [hellodb]> select * from teachers union select * from students;
MariaDB [hellodb]> 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 | 100 | M |
| 26 | xietingfeng | 23 | M |
| 27 | liudehua | 18 | F |
| 28 | mahuateng | 20 | M |
| 29 | wuyanzu | 19 | M |
| 30 | wuxin | 21 | M |
| 31 | Song Jiang | 45 | M |
| 32 | Zhang Sanfeng | 18 | M |
| 33 | Miejue Shitai | 18 | F |
| 34 | Lin Chaoying | 18 | F |
| 35 | 巴西可 | 20 | M |
| 36 | abc | 20 | M |
+----+---------------+-----+--------+
40 rows in set (0.001 sec)

MariaDB [hellodb]> 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 | 93 | F |
+-----+---------------+-----+--------+
4 rows in set (0.00 sec)

#UNION ALL不去重 UNION去重
MariaDB [hellodb]> 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 | 93 | F |
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |

MariaDB [hellodb]> select * from user union select * from user;
+------+----------+----------+
| id | username | password |
+------+----------+----------+
| 1 | admin | aki |
| 2 | ayaka| aki |
| 3 | aika | centos |

#DISTINCT合并相同的内容	DISTINCT 必须放在 SELECT 关键字后第一位
MariaDB [hellodb]> select distinct * from user ;
+------+----------+----------+
| id | username | password |
+------+----------+----------+
| 1 | admin | aki |
| 2 | ayaka| aki |
| 3 | aika | centos |

交叉连接

cross join 即多表的记录之间做笛卡尔乘积组合,并且多个表的列横向合并相加, "雨露均沾"
比如: 第一个表3行4列,第二个表5行6列,cross join后的结果为3*5=15行,4+6=10列
交叉连接生成的记录可能会非常多,建议慎用
范例:交叉连接

#横向合并,交叉连接(横向笛卡尔)
MariaDB [hellodb]> select * from students cross join teachers;
MariaDB [hellodb]> select * from teachers , students;
+-----+---------------+-----+--------+-------+---------------+-----+--------+---
------+-----------+
| TID | Name | Age | Gender | StuID | Name | Age | Gender |
ClassID | TeacherID |
+-----+---------------+-----+--------+-------+---------------+-----+--------+---
------+-----------+
| 1 | Song Jiang | 45 | M | 1 | Shi Zhongyu | 22 | M |
2 | 3 |
| 2 | Zhang Sanfeng | 94 | M | 1 | Shi Zhongyu | 22 | M |
2 | 3 |
| 3 | Miejue Shitai | 77 | F | 1 | Shi Zhongyu | 22 | M |
2 | 3 |
| 4 | Lin Chaoying | 26 | F | 1 | Shi Zhongyu | 22 | M |
2 | 3 |
| 1 | Song Jiang | 45 | M | 2 | Shi Potian | 22 | M |
1 | 7 |
| 2 | Zhang Sanfeng | 94 | M | 2 | Shi Potian | 22 | M |
1 | 7 |
| 3 | Miejue Shitai | 77 | F | 2 | Shi Potian | 22 | M |
1 | 7 |
| 4 | Lin Chaoying | 26 | F | 2 | Shi Potian | 22 | M |
1 | 7 |
| 1 | Song Jiang | 45 | M | 3 | Xie Yanke | 53 | M |
2 | 16 |
| 2 | Zhang Sanfeng | 94 | M | 3 | Xie Yanke | 53 | M |
2 | 16 |
| 3 | Miejue Shitai | 77 | F | 3 | Xie Yanke | 53 | M |
2 | 16 |
| 4 | Lin Chaoying | 26 | F | 3 | Xie Yanke | 53 | M |
......
#建议别用 我复制都复制到恶心了

MariaDB [hellodb]> 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 | 1 | Song Jiang | 45 |
| 1 | Shi Zhongyu | 22 | 2 | Zhang Sanfeng | 94 |
| 1 | Shi Zhongyu | 22 | 3 | Miejue Shitai | 77 |
| 1 | Shi Zhongyu | 22 | 4 | Lin Chaoying | 26 |
| 2 | Shi Potian | 22 | 1 | Song Jiang | 45 |
| 2 | Shi Potian | 22 | 2 | Zhang Sanfeng | 94 |
| 2 | Shi Potian | 22 | 3 | Miejue Shitai | 77 |
| 2 | Shi Potian | 22 | 4 | Lin Chaoying | 26 |
| 3 | Xie Yanke | 53 | 1 | Song Jiang | 45 |
| 3 | Xie Yanke | 53 | 2 | Zhang Sanfeng | 94 |
| 3 | Xie Yanke | 53 | 3 | Miejue Shitai | 77 |
| 3 | Xie Yanke | 53 | 4 | Lin Chaoying | 26 |
| 4 | Ding Dian | 32 | 1 | Song Jiang | 45 |
| 4 | Ding Dian | 32 | 2 | Zhang Sanfeng | 94 |
| 4 | Ding Dian | 32 | 3 | Miejue Shitai | 77 |
| 4 | Ding Dian | 32 | 4 | Lin Chaoying | 26 |
| 5 | Yu Yutong | 26 | 1 | Song Jiang | 45 |
| 5 | Yu Yutong | 26 | 2 | Zhang Sanfeng | 94 |
| 5 | Yu Yutong | 26 | 3 | Miejue Shitai | 77 |
| 5 | Yu Yutong | 26 | 4 | Lin Chaoying | 26 |
| 6 | Shi Qing | 46 | 1 | Song Jiang | 45 |
| 6 | Shi Qing | 46 | 2 | Zhang Sanfeng | 94 |
| 6 | Shi Qing | 46 | 3 | Miejue Shitai | 77 |
| 6 | Shi Qing | 46 | 4 | Lin Chaoying | 26 |
| 7 | Xi Ren | 19 | 1 | Song Jiang | 45 |
| 7 | Xi Ren | 19 | 2 | Zhang Sanfeng | 94 |
| 7 | Xi Ren | 19 | 3 | Miejue Shitai | 77 |
| 7 | Xi Ren | 19 | 4 | Lin Chaoying | 26
......

MariaDB [hellodb]> 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 ;

+-------+---------------+-------------+-----+---------------+-------------+
| stuid | student_name | student_age | tid | teacher_name | teacher_age |
+-------+---------------+-------------+-----+---------------+-------------+
| 1 | Shi Zhongyu | 22 | 1 | Song Jiang | 45 |
| 1 | Shi Zhongyu | 22 | 2 | Zhang Sanfeng | 94 |
| 1 | Shi Zhongyu | 22 | 3 | Miejue Shitai | 77 |
| 1 | Shi Zhongyu | 22 | 4 | Lin Chaoying | 26 |
| 2 | Shi Potian | 22 | 1 | Song Jiang | 45 |
| 2 | Shi Potian | 22 | 2 | Zhang Sanfeng | 94 |
| 2 | Shi Potian | 22 | 3 | Miejue Shitai | 77 |
| 2 | Shi Potian | 22 | 4 | Lin Chaoying | 26 |
| 3 | Xie Yanke | 53 | 1 | Song Jiang | 45 |
| 3 | Xie Yanke | 53 | 2 | Zhang Sanfeng | 94 |
| 3 | Xie Yanke | 53 | 3 | Miejue Shitai | 77 |
| 3 | Xie Yanke | 53 | 4 | Lin Chaoying | 26 |
| 4 | Ding Dian | 32 | 1 | Song Jiang | 45 |
| 4 | Ding Dian | 32 | 2 | Zhang Sanfeng | 94 |
| 4 | Ding Dian | 32 | 3 | Miejue Shitai | 77 |
| 4 | Ding Dian | 32 | 4 | Lin Chaoying | 26 |
| 5 | Yu Yutong | 26 | 1 | Song Jiang | 45 |
| 5 | Yu Yutong | 26 | 2 | Zhang Sanfeng | 94 |
......

内连接

inner join 内连接取多个表的交集

范例:内连接

#内连接inner join
MariaDB [hellodb]> select * from students inner join teachers on
students.teacherid=teachers.tid;

+-------+-------------+-----+--------+---------+-----------+-----+--------------
-+-----+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name
| Age | Gender |
+-------+-------------+-----+--------+---------+-----------+-----+--------------
-+-----+--------+
| 5 | Yu Yutong | 26 | M | 3 | 1 | 1 | Song Jiang
| 45 | M |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 3 | Miejue Shitai
| 77 | F |
| 4 | Ding Dian | 32 | M | 4 | 4 | 4 | Lin Chaoying
| 93 | F |
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+

#如果表定义了别名,原表名将无法使用
MariaDB [hellodb]> 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 |
+-------+--------------+-----+---------------+
| 5 | Yu Yutong | 1 | Song Jiang |
| 1 | Shi Zhongyu | 3 | Miejue Shitai |
| 4 | Ding Dian | 4 | Lin Chaoying |
+-------+--------------+-----+---------------+
3 rows in set (0.00 sec)

MariaDB [hellodb]> 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 | 45 | M | Miejue Shitai | 77 | F
|
| Shi Zhongyu | 45 | M | Lin Chaoying | 29 | F
|
| Shi Potian | 22 | M | Miejue Shitai | 77 | F
|
| Shi Potian | 22 | M | Lin Chaoying | 29 | F
|
| Xie Yanke | 77 | M | Miejue Shitai | 77 | F
|
| Xie Yanke | 77 | M | Lin Chaoying | 29 | F
|
| Ding Dian | 32 | M | Miejue Shitai | 77 | F
|
| Ding Dian | 32 | M | Lin Chaoying | 29 | F
|
| Yu Yutong | 26 | M | Miejue Shitai | 77 | F
|
| Yu Yutong | 26 | M | Lin Chaoying | 29 | F
|
| Shi Qing | 46 | M | Miejue Shitai | 77 | F
|
| Shi Qing | 46 | M | Lin Chaoying | 29 | F
|
| Xi Ren | 19 | F | Song Jiang | 45 | M
|
| Xi Ren | 19 | F | Zhang Sanfeng | 94 | M
|
| Lin Daiyu | 17 | F | Song Jiang | 45 | M
|
| Lin Daiyu | 17 | F | Zhang Sanfeng | 94 | M
|

MariaDB [hellodb]> select stuid,s.name,tid,t.name from students s,teachers t where s.teacherid=t.tid;
+-------+-------------+-----+---------------+
| stuid | name | tid | name |
+-------+-------------+-----+---------------+
| 5 | Yu Yutong | 1 | Song Jiang |
| 1 | Shi Zhongyu | 3 | Miejue Shitai |
| 4 | Ding Dian | 4 | Lin Chaoying |
+-------+-------------+-----+---------------+
3 rows in set (0.00 sec)

内连接后过滤数据
MariaDB [hellodb]> 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 |
+-------+-------------+-----+--------+---------+-----------+-----+--------------
+-----+--------+
| 25 | Sun Dasheng | 100 | M | NULL | 1 | 1 | Song Jiang
| 45 | M |
| 4 | Ding Dian | 32 | M | 4 | 4 | 4 | Lin Chaoying
| 26 | F |
+-------+-------------+-----+--------+---------+-----------+-----+--------------
+-----+--------+
2 rows in set (0.002 sec)

自然连接

  • 当源表和目标表共享相同名称的列时,就可以在它们之间执行自然连接,而无需指定连接列。

  • 在使用纯自然连接时,如没有相同的列时,会产生交叉连接(笛卡尔乘积)

  • 语法:

    SELECT table1.column, table2.column FROM table1 NATURAL JOIN table2;
    

范例:

MariaDB [db1]> create table t1 ( id int,name char(20));
MariaDB [db1]> create table t2 ( id int,title char(20));
MariaDB [db1]> insert t1 values(1,'mage'),(2,'wang'),(3,'zhang');
MariaDB [db1]> insert t2 values(1,'ceo'),(2,'cto');

MariaDB [db1]> select * from t1;
+------+-------+
| id | name |
+------+-------+
| 1 | mage |
| 2 | wang |
| 3 | zhang |
+------+-------+
3 rows in set (0.00 sec)

MariaDB [db1]> select * from t2;
+------+-------+
| id | title |
+------+-------+
| 1 | ceo |
| 2 | cto |
+------+-------+
2 rows in set (0.00 sec)

MariaDB [db1]> select * from t1 NATURAL JOIN t2;
+------+------+-------+
| id | name | title |
+------+------+-------+
| 1 | mage | ceo |
| 2 | wang | cto |
+------+------+-------+
2 rows in set (0.00 sec)

MariaDB [db1]> select t1.name,t2.title from t1 NATURAL JOIN t2;
+------+-------+
| name | title |
+------+-------+
| mage | ceo |
| wang | cto |
+------+-------+
2 rows in set (0.00 sec)

MariaDB [db1]> 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值填充

范例:左,右外连接

#左外连接
MariaDB [hellodb]> 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 | 93 |
| 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 | 100 | NULL | NULL | NULL | NULL |
+-------+---------------+-----+-----------+------+---------------+------+
25 rows in set (0.00 sec)

#左外连接扩展
MariaDB [hellodb]> 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 |
+-------+---------------+-----+--------+---------+-----------+------+------+----
--+--------+
21 rows in set (0.001 sec)


#多个条件的左外连接
#最终效果: * 由于连接条件永远无法匹配成功,teachers 表的所有字段在结果集中都将显示为 NULL。因为是 LEFT JOIN,students 表的所有行都会被列出来。但右侧关联的老师信息全部是空的。
MariaDB [hellodb]> 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 |
......



#先左外连接,再过滤
MariaDB [hellodb]> 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 |
........


#右外连接
MariaDB [hellodb]> select * from students s right outer join teachers t on
s.teacherid=t.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 |
| 25 | Sun Dasheng | 100 | M | NULL | 1 | 1 | Song Jiang
| 45 | M |
| NULL | NULL | NULL | NULL | NULL | NULL | 2 | Zhang
Sanfeng | 94 | M |
+-------+-------------+------+--------+---------+-----------+-----+-------------
--+-----+--------+
5 rows in set (0.001 sec)



#右外连接的扩展用法
MariaDB [hellodb]> 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.000 sec)

完全外连接

MySQL 不支持完全外连接full outer join语法

范例:完全外连接

#MySQL不支持完全外连接 full outer join,利用以下方式法代替
MariaDB [hellodb]> select * from students left join teachers on
students.teacherid=teachers.tid
-> union 	#(联合)
-> select * from students right join teachers on
students.teacherid=teachers.tid;

MariaDB [hellodb]> 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 | 93 |
| 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 | 100 | NULL | NULL | NULL |
| NULL | NULL | NULL | 2 | Zhang Sanfeng | 94 |
+-------+---------------+------+------+---------------+------+
26 rows in set (0.01 sec)



#完全外连接的扩展示例
MariaDB [hellodb]> 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 | 100 | M | NULL | NULL | NULL | NULL
| NULL | NULL |
| NULL | NULL | NULL | NULL | NULL | NULL | 2 | Zhang
Sanfeng | 94 | M |
+-------+---------------+------+--------+---------+-----------+------+----------
-----+------+--------+
23 rows in set (0.001 sec)


MariaDB [hellodb]> 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    selects.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 |
| NULL | NULL | NULL | 2 | Zhang Sanfeng |
| NULL | NULL | NULL | 5 | abc |
+-------+---------------+-----------+------+---------------+
23 rows in set (0.00 sec)

自连接

自连接, 即表自身连接自身

范例:自连接

#自连接
MariaDB [hellodb]>create table emp (id int,name varchar(10),leaderid int);
MariaDB [hellodb]>insert emp values (1,'aya',null),(2,'zhangsir',1),
(3,'wang',2),(4,'zhang',3);

MariaDB [hellodb]> select * from emp;
+------+----------+----------+
| id | name | leaderid |
+------+----------+----------+
| 1 | aya | NULL |
| 2 | zhangsir | 1 |
| 3 | wang | 2 |
| 4 | zhang | 3 |
+------+----------+----------+
4 rows in set (0.00 sec)

MariaDB [hellodb]> select e.name,l.name from emp as e inner join emp as l on e.leaderid=l.id;
+----------+----------+
| name | name |
+----------+----------+
| zhangsir | aya |
| wang | zhangsir |
| zhang | wang |
+----------+----------+
3 rows in set (0.00 sec)

MariaDB [hellodb]> select e.name,IFNULL(l.name,'无上级') from emp as e left
join emp as l on e.leaderid=l.id;
+----------+----------+
| name | name |
+----------+----------+
| zhangsir | aya |
| wang | zhangsir |
| zhang | wang |
| aya | NULL |
+----------+----------+
4 rows in set (0.00 sec)

MariaDB [hellodb]> select e.name emp,IFNULL(l.name,'无上级') leader from emp as e left join emp as l on e.leaderid=l.id;
+----------+----------+
| emp | leader |
+----------+----------+
| zhangsir | aya |
| wang | zhangsir |
| zhang | wang |
| aya | NULL |
+----------+----------+
4 rows in set (0.000 sec)

范例:三表连接

#三张表连接示例
MariaDB [hellodb]> 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.000 sec)


MariaDB [hellodb]> 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.001 sec)
MariaDB [hellodb]>

评论