SQL 查询与修改


前言

参考

  • 廖雪峰:https://www.liaoxuefeng.com/wiki/1177760294764384/1179610544539040
  • 菜鸟教程:
    https://www.runoob.com/sql/sql-like.html (推荐使用)

1 查询 SELECT

1.1 基本

  • 语句
    查询一张表的所有记录.
    SELECT * FROM <表名>;

1.2 条件

  • 语句
    SELECT * FROM <表名> WHERE <条件表达式>;

  • 特点
    返回的二维表结构和原表是相同的,即结果集的所有列与原表的所有列都一一对应。

  • 举例
    例1:从 students 表中查询 score 大于70的记录
    SELECT * FROM students WHERE score > 70;
    例2:查询分数在80分(含)~95分(含)之间的记录
    SELECT * FROM students WHERE 80 <= score AND score <= 95; //注意不能用 60 <= score <= 90

1.3 投影

  • 语句
    SELECT <列名1>, <列名2>, ..., <列名n> FROM <表名>;

  • 特点
    返回某些列的数据。

    可以对查询结果的列重命名,也可以通过WHERE加入查询条件。
    SELECT <列名1> [列名1别名], <列名2> [列名2别名], ..., <列名n> [列名n别名] FROM <表名> WHERE <条件表达式>;

  • 举例
    例1:从 students 表中查询 name 和 score 的记录,要求 score 大于90,name 改为 new_name;
    SELECT name new_name, score FROM students WHERE score > 70;

1.4 排序

  • 语句
    SELECT <列名1>, <列名2>, ..., <列名n> FROM <表名> ORDER BY <列名n> DESC/ASC;

  • 特点
    使用SELECT查询时,大部分数据库的做法是查询结果集通常是按照id排序的,也就是根据主键排序。如果我们要根据其他条件排序,就会用到ORDER BY <列名> ASC/DESC语句。

    1)默认的排序规则是ASC(ascend):“升序”,即从小到大。ASC可以省略,即ORDER BY score ASC和ORDER BY score效果一样。DESC,即 descend。
    2)如果有WHERE子句,那么ORDER BY子句要放到WHERE子句后面。
    SELECT <列名1>, <列名2>, ..., <列名n> FROM <表名> WHERE <条件表达式> ORDER BY <列名n> DESC/ASC;

  • 举例
    查询一班的学生成绩,并按照倒序排序:

      SELECT id, name, gender, score
      FROM students
      WHERE class_id = 1
      ORDER BY score DESC;
    

1.5 分页

1.6 聚合

如果我们要统计一张表的数据量,例如,想查询students表一共有多少条记录,难道必须用SELECT * FROM students查出来然后再数一数有多少行吗?

这个方法当然可以,但是比较弱智。对于统计总数、平均数这类计算,SQL提供了专门的聚合函数,使用聚合函数进行查询,它可以快速获得结果。

仍然以查询 students 表一共有多少条记录为例,我们可以使用 SQL 内置的 COUNT() 函数查询:SELECT COUNT(*) FROM students;

COUNT(*)表示查询所有列的行数,注意聚合的计算结果虽然是一个数字,但查询的结果仍然是一个二维表,只是这个二维表只有一行一列,并且列名是COUNT(*)。

  • 特点
    使用 SQL 提供的聚合查询,我们可以方便地计算总数、合计值、平均值、最大值和最小值。

  • 聚合函数

    函数 说明
    COUNT( * ) 计算有多少条记录
    SUM (列名) 计算某一列的合计值,该列必须为数值类型
    AVG (列名) 计算某一列的平均值,该列必须为数值类型
    MAX (列名) 计算某一列的最大值
    MIN (列名) 计算某一列的最小值
  • 举例
    使用聚合查询计算男生平均成绩。
    SELECT AVG(score) average FROM students WHERE gender = 'M';

    要特别注意:如果聚合查询的 WHERE 条件没有匹配到任何行,COUNT() 会返回0,而 SUM()、AVG()、MAX()和MIN()会返回 NULL

1.7 多表(笛卡尔)Cartesian

  • 语句
    SELECT * FROM <表名1> <表名2> ... <表名n>;
    多表查询又称笛卡尔查询,使用笛卡尔查询时要小心,由于结果集行数是目标表的行数乘积,对两个各自有1万行记录的表进行笛卡尔查询将返回1亿条记录。


    图 笛卡尔积

  • 举例
    例1:将同一张表进行笛卡尔积并显示

      SELECT
      	*
      FROM
      	students AS a, students AS b;   //重命名,'AS'可以省略。注意:组合的新表中,来自a表的列在左,b 表的列在右
    

    例2:通过条件进行笛卡尔查询

    多表查询也可以添加 WHERE 条件的。

      SELECT
      	s.id sid,   // 改列名,students 表中的 id 改为 sid
      	s.name,
      	s.gender,
      	s.score,
      	c.id cid,
      	c.name cname
      FROM students s, classes c;   // 改表名,students 改为 s
      WHERE s.gender = 'M' AND c.id = 1;   //查询条件
    

1.8 连接 JOIN

  • 概念
    连接查询是一种的多表查询。连接查询对多个表进行JOIN运算,简单地说,就是先确定一个主表作为结果集,然后,把其他表的行有选择性地“连接”在主表结果集上。

  • 举例:内连接
    选出所有学生,同时返回班级名称。

      SELECT s.id, s.name, s.class_id, c.name class_name, s.gender
      FROM student s
      INNER JOIN classes c   
      ON s.class_id= c.id;   //连接条件:通过 students 表的外键与 classes 表建立联系
    

    这里,使用了一种最常见的连接方式——内连接,语句是INNER JOIN <...> ON <...>

  • 内连接(INNER JOIN / JOIN)语法

    !!!注意:INNER JOIN 可以简写为 JOIN
    1)先确定主表,仍然使用FROM <表1>的语法;
    2)再确定需要连接的表,使用INNER JOIN <表2>的语法;
    3)然后确定连接条件,使用ON <条件...>,这里的条件是s.class_id = c.id,表示students表的class_id列与classes表的id列相同的行需要连接;
    4)可选:加上WHERE子句、ORDER BY等子句。

  • 外连接(Left/Right/Full OUTER JOIN)
    假设查询语句如下:
    SELECT ... FROM tableA ??? JOIN tableB ON tableA.column1 = tableB.column2;
    对于这么多种JOIN查询,到底什么使用应该用哪种呢?其实我们用图来表示结果集就一目了然了。

2 增加 INSERT

  • 语句
    INSERT INTO <表名> (列名1, 列名2, ...) VALUES (值1, 值2, ...);

  • 特点
    当需要向数据库表中插入一条新记录时,就必须使用INSERT语句。

  • 举例

      INSERT INTO students (class_id, name, gender, score) VALUES
        (1, '大宝', 'M', 87),
        (2, '二宝', 'M', 81);
    

    注意到我们并没有列出id字段,也没有列出id字段对应的值,这是因为id字段是一个自增主键,它的值可以由数据库自己推算出来。此外,如果一个字段有默认值,那么在INSERT语句中也可以不出现。

    要注意,字段顺序不必和数据库表的字段顺序一致,但值的顺序必须和字段顺序一致。也就是说,可以写INSERT INTO students (score, gender, name, class_id) ...,但是对应的VALUES就得变成(80, 'M', '大牛', 2)。

    还可以一次性添加多条记录,只需要在VALUES子句中指定多个记录值,每个记录是由(...)包含的一组值。

3 删除 DELETE

  • 语句
    DELETE FROM <表名> WHERE <条件表达式>;

    1)如果 WHERE 条件没有匹配到任何记录,DELETE 语句不会报错,也不会有任何记录被删除。
    2)要特别小心的是,不带 WHERE 条件的 DELETE 语句会删除整个表的记录。所以,在执行 DELETE 语句时也要非常小心,最好先用 SELECT 语句来测试 WHERE 条件是否筛选出了期望的记录集,然后再用DELETE 删除。

  • 举例

      DELETE FROM students;   //删除 students 表的所有记录,但是表依然存在
      DELETE FROM students WHERE score > 90;   //删除 students 表中 score 大于90记录
    

4 修改 UPDATE

  • 语句
    UPDATE <表名> SET 列名1=值1, 列名2=值2, ... WHERE ...;

    1)如果 WHERE 条件没有匹配到任何记录,UPDATE 语句不会报错,也不会有任何记录被更新。
    2)要特别小心的是,UPDATE 语句可以没有 WHERE 条件,例如:UPDATE students SET score=60;这时,整个表的所有记录都会被更新。所以,在执行 UPDATE 语句时要非常小心,最好先用 SELECT 语句来测试 WHERE 条件是否筛选出了期望的记录集,然后再用 UPDATE 更新。

  • 举例
    把所有80分以下的同学的成绩加10分,然后查询出来。

      UPDATE students SET score = score+10 WHERE score < 80;
      SELECT * FROM students;