SQL 注意事项 查询篇 SELECT

137 阅读3分钟

select 查询

1. 关键字顺序编写

SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...

2. SELECT 语句执行顺序

FROM> WHERE 条件 > GROUP BY 分组 > HAVING 筛选分组 > SELECT 字段 > DISTINCT > ORDER BY 排序 > LIMIT 查询数量

执行顺序举例:

SELECT DISTINCT
    player_id,
    player_name,
    count(*) AS num # 顺序 5
FROM
    player
    JOIN team ON player.team_id = team.team_id # 顺序 1
WHERE
    height > 1.80 # 顺序 2
GROUP BY
    player.team_id # 顺序 3
HAVING
    num > 2 # 顺序 4
ORDER BY
    num DESC # 顺序 6
LIMIT 2 # 顺序 7

3. limit 的使用

在实际系统中定义 select 查询语句时,应加上 limit 限制查询数据条数。

  • 一是防止查询数据过多,导致慢 SQL 语句的产生。
  • 二是保证查询的数据条数正常。

特殊情况:

  • 在使用分页工具时可不考虑,因为分页工具一般会拦截查询请求并对语句进行拼接
  • 要求查询全部数据的查询也尽可能地预估其数据量并加上 limit,除非数据量不可知

4. 展示列表、分页查询应加上 order by

  • 在分页查询时,有可能会出现同一条数据出现在不同页上、同一页的多次查询结果不一等情况 。这是由于数据库查询结果有可能因为插入或更新操作导致存储顺序不稳定。
  • 因此,应当在查询结果匹配数量较大的分页查询语句中,加上 order by。并提供一个能确定唯一数据行的字段用以排序,如主键、唯一约束键
  • 若该查询允许用户提供排序键,则应当将自定义排序字段放在唯一字段前

5. 使用 selectOne 要防止为 null

  • 在 MyBatis 中使用 selectOne 查询时,需要防止出现查不到数据的情况。
  • 当 SQL 语句查询为空时,selectOne 函数会返回 null。若用一个对象变量来接他的返回值,需要先判断他是否为 null 后再对其进行对象操作,防止出现空指针异常导致程序无法继续正常运行。
  • 技巧:在 Java 中可使用以下语句来简便对 null 的排除:
TestClass testClass = Optional.ofNullable(testClass).orElse(new TestClass());

6. 查询某数据是否存在:性能优化

  • 惯性思维是使用 count 函数计算结果来判断是否存在,但是这个操作会统计全表,在数据量大的表中耗时极高。
  • 可以用 select 1 limit 1 来判断是否存在,当数据库找到符合的数据时就会结束查询,不会统计全表。在 MyBatis 中,可以使用 selectOne 调用该 SQL 语句,并使用 Integer 包装类来接收返回值,通过判断返回是否为 null 来判断是否存在。若使用基础类型 int 可能会导致程序报错。 例子:
# SQL, id=hasClassStu
SELECT
    1 
FROM
    student 
WHERE
    class_id = '1' 
    LIMIT 1;
// Java
return session.selectOne("hasClassStu") != null;

7. SQL 函数、计算应该只在条件值上使用

  • SQL 函数、计算应该只在条件值上使用,即 where 条件中 = 的右边。
  • 若给数据库字段使用 SQL 函数、或进行计算会使得索引失效,因为这需要给全表的指定字段的所有值都进行计算后才能和条件比对。 正确例子:
SELECT
    id,
    stu_name,
    age 
FROM
    student_info 
WHERE
    age = 2020 - #{year};