# 总结

# 在 SQL 开发中容易犯的错误

  • 使用 count(*) 判断是否存在符合条件的数据

    可以使用 SELECT ... LIMIT 1 来,因为有优化

    注意:笔者这里没有 get 到点,到底说的是怎么判断?

  • 在执行一个更新语句后,使用查询方式判断此更新语句是否有执行成功

    可以使用 ROW_COUNT() 函数判断修改的行数

  • 试图在 ON 条件中过滤不满足条件的记录

    -- 查询出分类 iD = 5 的课程名称和分类名称
    select ic.class_id, i.title, ic.class_id
    from imc_class ic
             left join -- 这里使用了左外连接
             imc_course i on ic.class_id = i.class_id 
             and i.class_id = 5 -- 并在 ON 后面使用了 and 过滤
    -- 这里其实是一个坑,左外连接,左边全都出来,这里判定了一个右表的数据,所以就不满足我们的要求了
    
    1
    2
    3
    4
    5
    6
    7
  
  | class\_id | title | class\_id |
  | :--- | :--- | :--- |
  | 5 | MySQL课程-04097 | 5 |
  | 5 | MySQL课程-84741 | 5 |
  | 5 | SQLServer课程-84646 | 5 |
  | 5 | SQLServer课程-73954 | 5 |
  | 5 | MySQL课程-56069 | 5 |
  | 5 | PostgreSQL课程-49682 | 5 |
  | 5 | MySQL课程-53657 | 5 |
  | 1 | NULL | 1 |
  | 2 | NULL | 2 |
  | 3 | NULL | 3 |
  
  可以看到,不为 5 的也会出现,但是只有为 5 的 title 有数据,其他的没有是因为生效的是右边的过滤数据。右边都过滤掉了,这行数关联的部分就不会显示出来了
  
  **避免这种误操作的情况:**在 where 中过滤
  
- 在使用 IN 进行子查询的判断时,在列中未指定正确的表名

  如:`select A1 from A where A1 in (select A1 from B)`,这时尽管 B 中并不存在 A1 列的数据,也不会报错,而是会列出 A 表中的所有数据。

  ```sql
  -- 查询课程名称在 imc_user 中存在的 title;我们知道 在 imc_user 中根本就没有 title
  select * from imc_course where title in (select title from imc_user)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

这个错误不太好查找,因为不会报错。

避免:使用表名来限定列名称,如 imc_user.title 这就会报错了,该表中的确没有这个列

  • 对于表中定义的具有 not null 和 default 值的列,在插入数据时直接插入 NULL 值

# 知识点回顾

  • 如何使用 DCL 语句来管理数据库的访问
  • 如何使用 DDL 语句来建立数据库对象
  • 如何使用 DML 语句来操作数据库中的数据
  • MySQL 常用的系统函数
  • MySQL 8.0 新增的通用表达式和窗口函数
    • 通用表达式:代替子查询
    • 窗口函数:适合用在统计分析类的场景,提高效率
  • 在 SQL 开发中容易犯的错误