Chlx's Live

Back

如果你不明确写 ORDER BY,数据库系统绝对不保证返回结果的顺序。把它当成“完全随机”来对待是最安全的做法。

SQL 是一种结构化查询语言(Structured Query Language),专门用来与数据库打交道,目的是提供一种从数据库中读写数据的简单有效的方法。

DDL:#

数据定义语言(Data Definition Language)用于数据模式定义、规定一致性约束、为用户授权等。常

核心命令:CREATEALTERDROP

truncate (清空数据) 和 delete (是DML语句)只删除数据不删除表的结构(定义),执行 drop 语句,此表的结构也会删除

mysql字段类型#

Pasted image 20250725172142

char 和 varchar#

约束#

SQL 约束用于规定表中的数据规则

  • NOT NULL - 指示某列不能存储 NULL 值。
  • UNIQUE - 保证某列的每行必须有唯一的值。
  • PRIMARY KEY - NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。
  • FOREIGN KEY - 保证一个表中的数据匹配另一个表中的值的参照完整性。

AUTO_INCREMENT 不仅仅修饰主键(最常见场景),但必须修饰某个有索引的整数列

DML!数据操纵语言#

数据库数据的增删改查

核心命令:INSERTUPDATEDELETESELECT,合称 CRUD

INSERT into 表名 values (元组) 也可以插入部分列,其他列会被填充为默认值

UPDATE 表名 SET 列/属性 WHERE

DELETE FROM 表名

DQL:#

SELECT DISTINCT:返回唯一不同的值.作用于所有列,也就是说所有列的值都相同才算相同

LIMIT 限制返回的行数。可以有两个参数,第一个参数为起始行,从 0 开始;第二个参数为返回的总行数。

条件#

where and having 都是条件

执行顺序 where>聚合>having 分组之后查询的字段通常为聚合函数和分组字段 其他字段无意义

范围#

IN 和 BETWEEN(闭区间)

字段须是文本值 LIKE% 表示任何字符出现任意次数。_ 表示任何字符出现一次。

分组#

  • having 一般都是和 group by 连用,用于对汇总的 group by 结果进行过滤。

SELECT 列表里,除了聚合字段,剩下的所有普通字段,一个不落,全都要写进 GROUP BY 后面

排序#

order by 对多列排序的时候,先排序的列放前面,后排序的列放后面并且,不同的列可以有不同的排序规则。

DCL#

管理用户 控制权限GRANT 和 REVOKE

-- 创建⻆⾊并授权
CREATE ROLE 'clerk';
GRANT SELECT, INSERT, UPDATE ON course TO 'clerk';

-- 创建⽤户并赋予⻆⾊

CREATE USER 'user01'@'localhost' IDENTIFIED BY '123456';
GRANT 'clerk' TO 'user01'@'localhost';
SET DEFAULT ROLE 'clerk' TO 'user01'@'localhost';

-- 收回对 course 表的更新权限
REVOKE UPDATE ON course FROM 'clerk';
sql

函数#

SQL提供5个聚集函数 max min avg sum count

字符串 TRIM() 数值函数 RAND()返回0~1 日期函数 汇总函数 COUNT(列名):统计某一列中非 NULL 值的行数COUNT(常量):就等价于 COUNT(*)统计所有行数。  DISTINCT 可以让汇总函数值汇总不同的值

控制流程函数 IF(条件表达式, 值_if_true, 值_if_false) FROM (...) 得到的是一个临时结果集(派生表) 派生表必须有别名 CASE WHEN 条件1 THEN 结果1 [WHEN 条件2 THEN 结果2 ...] [ELSE 默认结果] END 动态升序/降序 如果想让男性的 GPA 升序,女性的 GPA 降序:

SELECT name, gender,gpa
FROM users
ORDER BY 
  CASE gender 
    WHEN 'male' THEN gpa
    ELSE -gpa  -- 负值实现降序
  END;
plaintext

case when 子句中,遇到null值会进入下一个判断条件

窗口函数 排序类

  • row_number():每行一个唯一递增编号(1,2,3…)
  • rank():相同值并列,后面跳号
  • dense_rank():相同值并列,但不跳号 窗口函数名(…) over (partition by 分组字段 order by 排序字段)

表关系 / 连接关系#

一对多 不推荐用外键约束 使用逻辑外键 一对一关系表 就是大表拆分成小表. 在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNIQUE) 多对多 :需要建立一张中间表,中间表中有两个外键字段,分别关联两方的主键。

多表查询#

SQL 先根据 ON 生成一张临时表,然后再根据 WHERE 对临时表进行筛选

直接查询的结果是两张表的笛卡尔积 Pasted image 20250912150036

子查询#

用小扩号嵌套select 根据子查询结果的不同分为:

  1. 标量子查询(子查询结果为单个值)
  2. 列子查询(子查询结果为一列,但可以是多行)IN ANY
  3. 行子查询(子查询结果为一行,但可以是多列)
  4. 表子查询(子查询结果相当于子查询结果是一张表)结果作为临时表联查 ,嵌套越多性能越低

尽量用 JOIN来代替子查询,因为 JOIN 往往能更好地利用索引。

相关子查询#

作用:集合判断

EXISTS vs IN 的本质区别

  • IN 关心的是“值”:子查询必须明确 SELECT 出具体的字段(比如姓名),用来给外层做比对。
  • EXISTS 关心的是“有没有”:子查询 SELECT 什么根本不重要(所以我们通常写 SELECT 1),它只关心能不能查到行数。要想让它准确判断某一个人的情况,就必须WHERE 把内外层表关联起来(也就是上一题跟你讲的“内外桥梁”)。

所以,记住这个铁律: EXISTS,子查询里必有 WHERE 关联外层表;如果子查询没写关联条件,那 99% 是写出 Bug 了!

WITH 子句(CTE)#

CTE 的本质,就是给一个复杂的子查询结果集“起个名字”,把它变成当前 SQL 语句生命周期内的一个“临时表”。 可以理解为局部变量 基础语法结构:

WITH 
  -- 定义第一个 CTE
  cte_name_1 AS (
    SELECT ... FROM ...
  ),
  -- 定义第二个 CTE,甚至可以引用第一个 CTE
  cte_name_2 AS (
    SELECT ... FROM cte_name_1 WHERE ...
  )
  

-- 最终的主查询
SELECT * FROM cte_name_2;
plaintext

连接查询!#

Pasted image 20260621191636

默认是内连接 INNER JOIN #

相当于查询A、B交集部分数据 用逗号分隔两张表(使用where是隐式内连接)

外连接#

  • 左外连接:查询左表所有数据(包括交集)
select 字段列表 from 表1 left [outer] join 表2  on  连接条件 ... ;
plaintext

显然左右可以相互转换

ON:是生成临时大表时的连接条件。在 LEFT JOIN 中,即使 ON 后面的条件不成立,左表的数据依然会保留(右表补 NULL)。 WHERE:是对已经生成好的临时大表进行最终过滤。如果不满足 WHERE 条件,这条数据就会被彻底踢出结果集。

SQL 先根据 ON 生成一张临时表,然后再根据 WHERE 对临时表进行筛选

  1. 自连接 可以是内也可是外连接 必须起别名

假设我们在开发一个电商系统,有两个基础表:用户表(User 表 A,在左边)订单表(Order 表 B,在右边)

  • INNER JOIN(内连接): A ∩ B

    • 效果: 只查询出“下过订单的用户”及其“对应的订单”。没有下过单的用户,以及由于脏数据导致找不到对应用户的订单,统统不显示。
  • LEFT JOIN(左外连接): A ∪ (A ∩ B)

    • 效果: 以左表(用户表 A)为基准。查出系统里的所有用户。如果这个用户下过单,就把订单信息拼接在后面;如果这个用户是个新注册的“白嫖党”,从来没下过单,那么查询结果里该用户的订单字段全部显示为 NULL
  • RIGHT JOIN(右外连接): B ∪ (A ∩ B)

    • 效果: 以右表(订单表 B)为基准。查出系统里的所有订单。正常情况下订单都有对应的用户,如果因为系统 Bug 导致某个订单失去了用户 ID,这条订单依然会被查出来,只不过它的用户信息部分是 NULL

组合/集合运算#

UNION 运算符将多个查询结果集合并为一个结果集。

UNION 基本规则:

  • 所有查询的列数和列顺序必须相同。
  • 每个查询中涉及表的列的数据类型必须相同或兼容。
  • 通常返回的列名取自第一个查询。

保留重复值使用 UNION ALL

where+or 会条件短路导致重叠行只出现一次

并集(union)、交集(intersect)、差集(except)是去重的。 保留重复必须用 all 。即 union all 、 intersect all 、 except all

SQL基础
https://lixuan.live/blog/sql-ji-chu
Author Chlx
Published at 2025年10月11日
Comment seems to stuck. Try to refresh?✨