QL基础语言

  • SQL的分类:

    • DDL:(数据定义语言)(Data Definition Language) 对库和表进行操作,库和表结构的创建、修改、删除;

      • create 创建库、表、索引、视图、用户

      • alter 修改库字符集、表结构、索引、视图、用户、密码

      • drop 删除各种结构、库、表、视图、索引、用户

      • show 显示库、表

    • DML:(数据操纵语言) (Data Manipulation Language) 对表中的数据内容进行添加、修改、删除

      • insert 在表中插入、添加数据

      • update 修改表中的内容

      • delete 删除表中的内容

    • DQL:(数据查询语言) (Data Query Language) 对表中数据进行查询操作

      • select 根据条件查询内容、可以配合函数使用。

    • DCL:(数据控制语言) (Data Control Language) 对数据库进行权限管理、用户管理、事务管理

      • use 切换数据库

      • grant 权限设置

      • revoke 移除权限

    • DTL:(事务控制语言) (Data Transaction Language)

      • commit 事务提交

      • rollback 回滚

总结:需要记下来并且能默写

  • create 创建库、表、索引、视图、用户

  • alter 修改库字符集、表结构、索引、视图、用户、密码

  • drop 删除各种结构、库、表、视图、索引、用户

  • show 显示库、表

  • insert 在表中插入、添加数据

  • update 修改表中的内容

  • delete 删除表中的内容

  • select 根据条件查询内容、可以配合函数使用

  • use 切换数据库

  • grant 权限设置

  • revoke 移除权限

  • commit 事务提交

  • rollback 回滚

操作总结:

创建创建数据库

 -- 基础创建库
 CREATE DATABASE school;
 ​
 拆解:CREATE         # 创建(库/表)
        DATABASE     # 创建库
        school       # 库名
 ​
 -- 安全创建库(存在则忽略)
 CREATE DATABASE IF NOT EXISTS school 
 CHARACTER SET utf8mb4 
 ​
 拆解:IF NOT EXISTS                # 仅当数据库不存在时才创建,存在则忽略(不会报错)
        CHARACTER SET utf8mb4      # 指定使用 UTF-8 MB4

查看/切换/删除

 -- 查看所有数据库
 SHOW DATABASES;
 ​
 -- 查看数据库里所有的表
 SHOW TABLES;
 ​
 -- 切换数据库
 USE 库名;
 ​
 -- 查看当前所在数据库
 SELECT DATABASE();
 ​
 -- 查看表结构(两种方式)
 DESC 表名;
 ​
 -- 查看表结构
 SHOW COLUMNS FROM 表名;
 ​
 -- 查看建表语句
 SHOW CREATE TABLE 表名;
 ​
 -- 删除数据库(谨慎!)
 DROP DATABASE school;
 ​
 -- 或安全删除
 DROP DATABASE IF EXISTS school;
 ​
 -- 删除表(谨慎!)
 DROP TABLE 表名;
 ​
 -- 安全删除
 DROP TABLE IF EXISTS 表名;

创建表操作

 -- 基础创建表
 CREATE TABLE school (
 id INT,
 name VARCHAR(20),
 age VARCHAR(3)
 );
 ​
 拆解:CREATE         # 创建(库/表)
        TABLE        # 创建表
        school       # 表名
 ​
 格式介绍:
 # 可以加comment '注释信息' 团队协作或后期维护,能让人看懂字段的用途。
 # 数据限制类型包括varchar、char
 CREATE TABLE 表名 (
 列名1 数据类型 comment '注释信息',
 列名2 数据类型 约束条件,
 列名3 数据类型(数据限制),
 );
 ​
 案例:
 create table `库名`.`表名`(                   # 在数据库中创建一张表
 id int,                                     # 整型,学生编号
 name varchar(30),                           # 可变长度字符串,最大30个字符,姓名
 gender enum('男','女'),                      # 枚举类型,只能选'男'或'女',性别
 birthday date                               # 日期类型(格式:YYYY-MM-DD)生日
 age INT CHECK (age >= 18 AND age <= 65)     # 年龄必须在 18-65 之间
 );
 ​
 # 数据类型:用于规范数据列的内容;
 int             # 整数
 bigint          # 长整数
 check           # 限制列中值的范围或条件
 char            # 定长字符串(18)
 varchar         # 变长字符串varchar(18)节省储存空间,性能稍微
 enum            # 枚举类型,本质也是字符类型,类似单选框只能从已有选项中,选择一个添加
 set             # 集合类型,字符串,可选一个或多个选择
 text            # 文本类型65,535 字节 (约 64 KB)
 longtext        # 大文本类型4,294,967,295 字节 (约 4 GB)
 float           # 浮点类型,普通小数,精确度低,约6-7位有效数字
 double          # 双精度浮点类型,比float精度高一倍,约15-16位有效数字
 decimal         # 小数,本质是以字符方式储存数据decimal(20,10) (总位数,小数位)
 date            # 日期类型 'YYYY-MM-DD'
 time            # 时间类型 'HH:MM:SS'
 datetime        # 时间日期类型 'YYYY-MM-DD HH:MM:SS'  【建议使用】
 TIMESTAMP       # 时间戳 'yyyymmddhhmmss'
 ​
 # 约束条件:对数据列或表进行设置与约束
 ## 表级约束
 engine          # 存储引擎
 charset         # 字符集
 ​
 ## 行级约束
 PRIMARY KEY         # 主键,唯一、不能为空,精确查询;
 unsigned            # 无符号,数字只能为正数,不能为负数;
 not null            # 不能为空,不添加数据会报错;
 auto_increment      # 自动增长,整数添加,自动+1;
 unique key          # 值唯一,不能重复;                
 foreign key         # 外键约束,用于多表连接查询;
 default             # 设置默认值   
 ​
 ## 约束补充
 - 检查约束(CHECK)
   - 作用:限制列中值的范围或条件(MySQL 8.0.16及以上支持)
 - 自增约束(AUTO_TNCREMENT)
   - 作用:自动为新记录生成唯一的递增数值,通常与主键配合使用。
 ​

修改表操作

  -- 添加字段(表添加一个新的列)
   ALTER TABLE 表名 ADD 列名 VARCHAR(20);
 ​
  -- 修改字段类型(修改某一列的数据类型)
   ALTER TABLE 表名 MODIFY 列名 TINYINT;
 ​
  -- 重命名字段(给列名重命名,能同时修改列名和数据类型)
   ALTER TABLE 表名 CHANGE 旧列名 新列名 VARCHAR(10);
 ​
  -- 删除字段(删除某一列,COLUMN可忽略)
   ALTER TABLE 表名 DROP COLUMN 列名;
 ​
  -- 重命名表(给表重新改一个名字)
   ALTER TABLE 旧表名 RENAME TO 新表名;

数据操作(CRUD)

 -- 插入完整数据
   INSERT INTO students (id, name ,gender) 
   VALUES (1, '安某某', '女');
 ​
 -- 插入完整数据(中文版)
   INSERT INTO 表名 (`编号`, `姓名`, `性别`) 
   VALUES (1, '安某某', '女');
 ​
 -- 插入多条数据(中文版)
   INSERT INTO 表名 (`编号`, `姓名`, `性别`)
   VALUES (2, '张三', '男'),
          (3, '李四', '女');
 ​
 -- 插入部分字段(中文版)
   INSERT INTO 表名 (`编号`, `姓名`) VALUES (4, '王五');
 ​
 -- 从其他表复制数据
   INSERT INTO 被复制表 SELECT * FROM 表名;

表数据查询

 -- 查询所有(查看表里面的数据)
   SELECT * FROM 表名;
 ​
 -- 查询指定字段
   SELECT 列名,列名 FROM 表名;
 ​
 -- 条件查询
   SELECT * FROM 表名 WHERE id(列名) = 1;
   SELECT * FROM 表名 WHERE gender(列名) = '女' AND age(列名) > 18;
   SELECT * FROM 表名 WHERE gender(列名) = '男' OR age(列名) > 20;
 ​
   # 运算符  含义    效果
     AND   逻辑与   所有条件都满足才返回 TRUE
     OR    逻辑或   任意一个条件满足就返回 TRUE
 ​
 -- 模糊查询
   SELECT * FROM 表名 WHERE 列名 LIKE '安%';  -- 以"安"开头
   SELECT * FROM 表名 WHERE 列名 LIKE '%倩';  -- 以"倩"结尾
   SELECT * FROM 表名 WHERE 列名 LIKE '%张%'; -- 包含"张"
 ​
 -- 排序
   SELECT * FROM 表名 ORDER BY 列名 DESC;  -- 降序
   SELECT * FROM 表名 ORDER BY 列名 ASC;   -- 升序
 ​
   # ORDER BY 对查询结果排序  ASC/升序  DESC/降序
 ​
 -- 分页
   SELECT * FROM 表名 LIMIT 10;            -- 前10条
   SELECT * FROM 表名 LIMIT 10 OFFSET 20;  -- 第21-30条
 ​
   # LIMIT 10    限制返回行数,只返回前 10 条记录
   # OFFSET 20   跳过前 20 条记录,从第 21 条开始取
 ​
 -- 聚合查询
   SELECT COUNT(*) FROM 表名;              -- 统计表中总共有多少条记录
   SELECT AVG(列名) FROM 表名;              -- 计算表中某一列所有数值的平均值
   SELECT gender(列名), COUNT(*) FROM 表名 GROUP BY gender(列名); -- 按性别分组,统计每个性别各有多少人。

修改数据

 -- 更新单条数据
   UPDATE 表名 SET 列名(性别) = '男' WHERE 列名(id) = 1;
 ​
 -- 更新多条数据
   UPDATE 表名 SET 列名(年龄) = 20 WHERE 列名(性别) = '女';
 ​
 -- 更新多个字段
   UPDATE 表名 SET 列名(姓名) = '赵六', 列名(年龄) = 22 WHERE 列名(id) = 4;
 ​
 -- ⚠️ 忘记WHERE的后果(更新所有行!)
   UPDATE 表名 SET 列名(年龄) = 18;  -- 所有学生年龄都变成18

删除数据

 -- 删除指定记录
   DELETE FROM 表名 WHERE 列名(id) = 1;
 ​
 -- 删除所有记录(保留表结构)
   DELETE FROM 表名;
 -- 或快速清空
   TRUNCATE TABLE 表名;
 ​
 -- ⚠️ 忘记WHERE的后果(删除所有数据!)
   DELETE FROM `学生信息`;  -- 所有数据被删除

约束(Constraint)

 CREATE TABLE `学生信息` (
     `编号` INT PRIMARY KEY AUTO_INCREMENT,              -- 主键+自增
     `姓名` VARCHAR(20) NOT NULL,                        -- 非空
     `邮箱` VARCHAR(50) UNIQUE,                          -- 唯一
     `年龄` INT DEFAULT 18,                              -- 默认值
     `班级` VARCHAR(20),
     FOREIGN KEY (`班级`) REFERENCES `班级表`(`班级编号`)  -- 外键
 );

数据类型查询

数据类型查询表

1. 整数型

类型

字节

范围(有符号)

范围(无符号)

TINYINT(m)

1

(-128,127)

(0,255)

SMALLINT(m)

2

(-32768,32767)

(0,65535)

MEDIUMINT(m)

3

(-8388608,8388607)

(0,16777215)

INT(m)

4

(-2147483 648,2147483647)

(0,4294967295)

BIGINT(m)

8

(-9223372036854775808,9223372036854775807)

(0,18446744073709551615)

类型后面括号里的m指的是显示宽度,显示宽度与所能存储的数据范围无关,目前已知的是当设置了ZEROFILL(填充0)约束条件时,填充 0的 个数由m决定

2. 浮点数和定点数

类型

大小

用途

FLOAT

4字节 :小数位过多会自动四舍五入

单精度浮点数值

DOUBLE

8字节

双精度浮点数值

DECIMAL

对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2

小数值

3. 日期时间

类型

字节

范围

格式

用途

DATE

3

1000-01-01/9999-12-31

YYYY-MM-DD

日期值

TIME

3

'-838:59:59'/'838:59:59'

HH:MM:SS

时间值或持续时间

YEAR

1

1901/2155

YYYY

年份值

DATETIME

8

1000-01-01 00:00:00/9999-12-31 23:59:59

YYYY-MM-DD HH:MM:SS

混合日期和时间值

TIMESTAMP

4

1970-01-01 00:00:00/2038 结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07

YYYYMMDD HHMMSS

混合日期和时间值,时间戳

4. 字符串类型

类型

大小

用途

CHAR(100)

0-255字节

定长字符串,有可能浪费存储空间

VARCHAR(100)

0-65535 字节

变长字符串,节约空间,性能不如CHAR

TINYBLOB

0-255字节

不超过 255 个字符的二进制字符串

TINYTEXT

0-255字节

短文本字符串

BLOB

0-65 535字节

二进制形式的长文本数据

TEXT

0-65 535字节

长文本数据

MEDIUMBLOB

0-16 777 215字节

二进制形式的中等长度文本数据

MEDIUMTEXT

0-16 777 215字节

中等长度文本数据

LONGBLOB

0-4 294 967 295字节

二进制形式的极大文本数据

LONGTEXT

0-4 294 967 295字节

极大文本数据

安全模式

 # 查看安全模式是否开启
 ## 需要进入mysql执行操作(关闭状态)
 mysql> show variables like 'sql_safe_updates';
 +------------------+-------+
 | Variable_name    | Value |
 +------------------+-------+
 | sql_safe_updates | OFF   |
 +------------------+-------+
 1 row in set (0.25 sec)
 ​
 ## 需要进入mysql执行操作(开启状态)
 mysql> show variables like 'sql_safe_updates';
 +------------------+-------+
 | Variable_name    | Value |
 +------------------+-------+
 | sql_safe_updates | ON    |
 +------------------+-------+
 1 row in set (0.01 sec)
 ​
 # 临时开启(exit退出后失效)
 ## 需要进入mysql执行操作
 set  sql_safe_updates = 1;
 ​
 # 永久开启,修改配置文件
 vim /etc/my.cnf                             # mysql配置文件
 ​
 # 每次开启MySQL时,自动加载文件中的操作
 ## 在/etc/my.cnf的[mysqld]最下面添加(自动加载文件)
 init-file=/usr/local/mysql/init-file.sql    # init-file= 固定语句 后面跟随路径
 ​
 # 创建init-file.sql并在里面配置加载参数
 ## vim 创建init-file.sql
 vim  /usr/local/mysql/init-file.sql         # 创建加载配置文件
 ​
 ## 在init-file.sql里面添加以下内容(安全模式)
 set  global sql_safe_updates = 1;           # 每次开启MySQL时,自动加载文件中的操作
 ​
 # 修改文件属主及属组权限(保持mysql文件权限统一性)
 chown mysql:mysql /usr/local/mysql/init-file.sql
 ​
 # 重启mysql服务
 systemctl restart mysqld

外键(FOREIGN KEY)

外键是用于关联两个表的约束,确保表之间的数据关联性和一致性。

  • 主表:被从表(包含外键的表)通过主键关联。

  • 核心作用强制从表(含外键的表)的某个字段值必须对应主表(被引用的表)中已存在的主键值。

  • 在从表中创建外键,外键字段对应主表的主键,并且外键对应的主键必须存在,才能被录入,否则会报错;

  • 但是生产环境使用时要注意,外键会影响写入性能,对于性能要求较高的应用,不建议使用外键,可以使用后端程序进行一致性和完整性验证;

  • 示例场景 主表students(学生信息)和从表scores(成绩信息)通过外键关联,确保成绩表中的学生必须是学生表中已存在的。

     -- 主表:学生表
     CREATE TABLE students (         -- 创建 students表名
       `学生ID` INT PRIMARY KEY,
       `姓名` VARCHAR(50)
     );
     ​
     -- 从表:成绩表
     CREATE TABLE scores (           -- 创建 scores表名
       `成绩ID` INT PRIMARY KEY,
       `ID学生` INT,              -- ✅ 字段名:ID学生
       `分数` INT,
       FOREIGN KEY (`ID学生`) REFERENCES students(`学生ID`)  -- ✅ 引用正确的字段名
         ON DELETE CASCADE
     );
  • 外键规则 当主表数据被修改时,可通过ON DELETEON UPDATE定义从表的行为(如CASCADE级联删除、SET NULL设为NULL等)。

总结

  • 约束条件是保障数据规则的“工具集”(主键、外键、非空等);

  • 外键是约束的一种,专门用于维护表之间的关联关系;

  • 完整性是数据符合规则的“状态”(实体、域、参照等维度);

  • 唯一性是数据的“属性”,确保字段值不重复(通过主键或唯一约束实现)。

    合理使用这些机制,能有效保证数据库数据的准确性、一致性和可靠性。

SQL查询

SQL常见查询条件(where前表名后列名)

条件类型

运算符/关键字

描述说明

示例代码

基础比较

=

等于

SELECT * FROM users WHERE gender = '男';从users表中,把性别为‘男’的过滤出来

!= / <>

不等于

SELECT * FROM products WHERE category != '服装';从 products(商品/产品)表中,查询出所有分类“不是”服装的商品记录

> / <

大于/小于

SELECT * FROM orders WHERE total_amount > 2000;从 orders(订单)表中,查询出所有总金额大于 2000 的订单记录,数字大于2000 (CHAR_LENGTH)数字转字符串查询

> / <

大于/小于

SELECT * FROM person WHERE CHAR_LENGTH(address) > 5;从person(表名)中,查询address(列名)字符数大于5的

>= / <=

大于等于/小于等于

SELECT * FROM users WHERE age <= 30;从 users(用户)表中,查询出所有年龄小于或等于 30 岁的用户记录

范围查询

BETWEEN ... AND ...

在闭区间内(含边界)

SELECT * FROM products WHERE price BETWEEN 100 AND 200;从 products(商品/产品)表中,查询出价格在 100 到 200 之间(包含 100 和 200)的所有商品记录。

IN (...)

在指定的值列表中

SELECT * FROM users WHERE city IN ('北京','上海','广州'); 从 users(用户)表中,查询出所有所在城市为“北京”、“上海”或“广州”的用户记录

模糊查询

LIKE%_

字符串模式匹配

SELECT * FROM articles WHERE title LIKE '%数据库%';从 articles(文章)表中,查询出标题(title)中包含“数据库”这三个字的所有文章记录

空值判断

IS NULL

判断是否为空值

SELECT * FROM logs WHERE deleted_at IS NULL; 从 logs(日志)表中,查询出所有“未被删除”(有效)的日志记录

IS NOT NULL

判断是否为非空值

SELECT * FROM users WHERE phone IS NOT NULL;从 users(用户)表中,查询出所有填写了手机号码(即 phone 字段不为空)的用户记录

逻辑组合

AND

多个条件同时满足

SELECT * FROM emp WHERE salary > 8000 AND dept = '技术部';从 emp(员工)表中,查询出属于“技术部”且薪水大于 8000 的所有员工记录

OR

多个条件满足其一

SELECT * FROM products WHERE category = '电子' OR price < 100;从 products(商品/产品)表中,查询出所有属于“电子”分类的商品,或者价格低于 100 的商品

NOT

取反条件

SELECT * FROM users WHERE NOT city = '北京';

去重查询

DISTINCT

去除结果中的重复记录(筛选唯一值)

SELECT DISTINCT category FROM products;从 products(商品/产品)表中查询所有的商品分类,并自动去除重复项,只保留唯一的分类列表

分组查询

GROUP BY

按字段分组聚合

SELECT dept, COUNT(*) FROM emp GROUP BY dept;按照部门统计员工数量

分组后筛选

HAVING需要先执行分组查询才能执行这个

对分组结果进行过滤

SELECT dept, COUNT(*) FROM emp GROUP BY dept HAVING COUNT(*) > 5;统计员工人数超过 5 人的部门

结果排序

ORDER BY ... ASC

按字段升序排列

SELECT * FROM products ORDER BY price ASC;从 products(商品/产品)表中查询所有字段的数据,并按照价格从低到高进行排序

ORDER BY ... DESC

按字段降序排列

SELECT * FROM products ORDER BY create_time DESC;从 products(商品/产品)表中查询所有字段的数据,并按照创建时间从新到旧进行排序

多字段排序

先按第一个字段排,再按第二个字段排

SELECT * FROM users ORDER BY city ASC, age DESC;从 users(用户)表中查询所有用户信息,首先按所在城市(city)进行升序排列(A-Z),在同一个城市内,再按照年龄(age)进行降序排列(从大到小)

结果分页

LIMIT ... OFFSET ...(MySQL)参数顺序:先跳过 再取

跳过N条取M条

SELECT * FROM users ORDER BY id LIMIT 10 OFFSET 20; 从 users(用户)表中查询所有字段的数据,按 ID 升序排列,并跳过前 20 条记录,只返回接下来的 10 条记录

LIMIT 起始位置, 条数

从指定位置开始返回N条记录(起始从0开始)

SELECT * FROM orders ORDER BY id LIMIT 10, 5; -- 第11-15条记录;从 orders(订单)表中查询所有字段的数据,按订单 ID 升序排列,跳过前 10 条记录,只返回接下来的 5 条记录

LIMIT 条数

只返回前N条记录

SELECT * FROM products ORDER BY price DESC LIMIT 5;从 products(商品/产品)表中,查询出价格最高的前 5 名商品记录

FETCH ... OFFSET ...(SQL Server/PostgreSQL)参数顺序:先取再跳过

跳过N条取M条

SELECT * FROM users ORDER BY id OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;从 users(用户)表中查询所有字段的数据,按 ID 升序排列,并跳过前 20 条记录,只返回接下来的 10 条记录

分页公式

LIMIT (N-1)*M, M第N页(每页M条):

SELECT * FROM users LIMIT 20, 10; -- 第3页,每页10条

例子解析:SELECT * FROM users LIMIT 20, 10; 跳过前20条,返回10条 → 第21-30条 → 第3页(每页10条)所以第三页是从21条开始

子查询相关

EXISTS

子查询有结果则成立

SELECT * FROM users WHERE EXISTS (SELECT 1 FROM orders WHERE user_id = users.id);从 users(用户)表中,查询出所有“下过订单”的用户记录

NOT EXISTS

子查询无结果则成立

SELECT * FROM products WHERE NOT EXISTS (SELECT 1 FROM orders WHERE product_id = products.id);从 products(商品/产品)表中,查询出所有“从未被下过订单”的商品记录

聚合函数

max

最大值

SELECT max(price) FROM products; 从 products(表名)表中查询(price)【列名】中最高的值

min

最小值

SELECT min(price) FROM products; 从 products(表名)表中查询(price)【列名】中最低的值

sum

求和

SELECT sum(price) FROM products; 计算 products (表名)表中(price)【列名】中的总和

avg

平均值

SELECT avg(price) FROM products; 计算 products (表名)表中(price)【列名】中的平均值

count

数量

SELECT count(*) FROM users; 统计 users(表名)表中的总记录数

例子:

count 搭配筛选条件

数量

SELECT COUNT(*) FROM users WHERE age > 18; 统计 users(表名)表中(age)【列名】统计年龄大于18岁的总数量

as

起别名

SELECT min(price) as "最贵" FROM products;

CHAR_LENGTH()LENGTH() 的区别(避坑指南)

  • CHAR_LENGTH(str)

    :返回字符数,无论中文还是英文,一个汉字算 1 个长度。

    • 例子:CHAR_LENGTH('你好') -> 结果 2

  • LENGTH(str)

    :返回字节数 ,这取决于数据库的编码格式。

    • 英文字母、数字、标点:每个占 1 字节。

    • 中文汉字:每个占 3 字节。

    • Emoji 表情:每个占 4 字节。

    • 特殊符号或生僻字:可能占 2~4 字节不等。

    • 例子:LENGTH('你好') -> 结果 6

  • 建议:如果你是指“字数”(即几个字),请务必使用 CHAR_LENGTH()

WHERE 普通查询,通过条件,过滤出结果

HAVING 根据分组后的结果在进行条件过滤

SELECT user_id, SUM(total_amount) FROM orders GROUP BY user_id HAVING SUM(total_amount) < 5000;

多表连接查询

  • 交叉连接(笛卡尔积连接):连接查询时,没有指定条件或条件错误导致,两张表中的内容进行排列组合;

  • 内连接 JOIN:只返回有关联关系的结果;

  • 外连接

    • 左(外)连接:完整显示左表中的所有数据,右边显示关联数据,没有关联数据显示NULL;

    • 右(外)连接:完整显示右表中的所有数据,左边显示关联数据,没有关联数据显示NULL;

  • 联合查询

交叉连接(笛卡尔积连接):select * from 表名 join 表名;

例子:select * from users join products;

内连接 JOIN:select * from 表名 inner join 表名 on 表名.id = 表名.id;(inner可省略)

例子:select * from users join products on users.id = products.id;

外连接:

左连接:select * from 表名 left join 表名 on 表名.id = 表名.id;

例子:select * from users left join products on users.id = products.id;

右连接:select * from 表名 right join 表名 on 表名.id = 表名.id;

例子:select * from users right join products on users.id = products.id;

别名连接:select * from 表名 别名 join 表名 别名 on 别名.id = 别名.id

例子:select * from user u join products p on u.id = p.id

别名连接简化查询:在后面加上 where 别名.列名 > 筛选条件;

例子:select * from user u join products p on u.id = p.id where p.price > 10000;

核心一句话总结:

  • 内连接:只要双方都有,我才要。

  • 左连接左边的全部要,右边有的就带上,没有就填 NULL

  • 右连接右边的全部要,左边有的就带上,没有就填 NULL

三表连接查询:使用外键关联三张表;

 SELECT *                                
 FROM orders o
 JOIN users u ON o.user_id = u.id
 JOIN products p ON o.product_id = p.id;
 ​
 拆解:
 🔍关联用户表
 JOIN users u              -- ① 关联表:users(用户表)
                        -- ② 别名:u
                        -- ③ 连接类型:JOIN = INNER JOIN(内连接)
 ON o.user_id = u.id       -- ④ 关联条件:订单的 user_id = 用户的 id
 ​
 🔍关联商品表
 JOIN products p           -- ① 关联表:products(商品表)
                        -- ② 别名:p
                        -- ③ 连接类型:JOIN = INNER JOIN(内连接)
 ON o.product_id = p.id    -- ④ 关联条件:订单的 product_id = 商品的 id
 SELECT 
  o.id AS 订单号,
  u.name AS 用户名,
  p.name AS 商品名,
  o.quantity AS 数量,
  o.total_amount AS 金额
 FROM orders o
 JOIN users u ON o.user_id = u.id
 JOIN products p ON o.product_id = p.id;
 ​
 拆解:
 🔍选择指定列(带中文别名)
 SELECT 
  o.id AS 订单号,            -- ① 从 orders 表取订单ID,显示为"订单号"
  u.name AS 用户名,          -- ② 从 users 表取用户名,显示为"用户名"
  p.name AS 商品名,          -- ③ 从 products 表取商品名称,显示为"商品名"
  o.quantity AS 数量,        -- ④ 从 orders 表取购买数量,显示为"数量"
  o.total_amount AS 金额     -- ⑤ 从 orders 表取订单总金额,显示为"金额"
 ​
 🔍指定主表
 FROM orders o                 -- ① 主表:orders(订单表)
                            -- ② 别名:o
 ​
 🔍关联用户表
 JOIN users u                 -- ① 关联表:users(用户表)
                           -- ② 别名:u
                           -- ③ 连接类型:JOIN = INNER JOIN(内连接)
 ON o.user_id = u.id          -- ④ 关联条件:订单的 user_id = 用户的 id

联合查询:

UNION:合并结果集并自动去除重复记录;

UNION ALL:合并结果集但保留重复记录(效率比UNION高);

 UNION合并结果集并自动去除重复记录方式(合并结果集但保留重复记录:UNION ALL):
 ​
 -- 查询价格低于200的商品和年龄小于25的用户
 SELECT '商品' AS 类型, name AS 名称, '价格低' AS 描述
 FROM products
 WHERE price < 200
 ​
 UNION
 ​
 SELECT '用户' AS 类型, username AS 名称, '年龄小' AS 描述
 FROM users
 WHERE age < 25;
 ​
 拆解:
 🔍 上半部分:查询商品数据
 SELECT '商品' AS 类型,       -- ① 常量字符串:固定显示"商品"
  name AS 名称,        -- ② 从 products 表取商品名称
  '价格低' AS 描述      -- ③ 常量字符串:固定显示"价格低"
 FROM products              -- ④ 数据来源:商品表
 WHERE price < 200;         -- ⑤ 筛选条件:价格低于 200
 ​
 🔍 下半部分:查询用户数据
 SELECT '用户' AS 类型,        -- ① 常量字符串:固定显示"用户"
  username AS 名称,     -- ② 从 users 表取用户名
  '年龄小' AS 描述       -- ③ 常量字符串:固定显示"年龄小"
 FROM users                  -- ④ 数据来源:用户表
 WHERE age < 25;             -- ⑤ 筛选条件:年龄小于 25
 ​
 注:-- 这条语句会真的创建一张名为 summary_report 的新表
 CREATE TABLE summary_report AS
 SELECT '商品' AS 类型, name AS 名称, '价格低' AS 描述
 FROM products
 WHERE price < 200
 ​
 UNION
 ​
 SELECT '用户' AS 类型, username AS 名称, '年龄小' AS 描述
 FROM users
 WHERE age < 25;