总言
主要内容:表的增删查改(DML操作)。insert插入(包含插入更新、插入查询),replace替换。select查询(包含列别名、distinct去重、where条件筛选、order排序、limit子句、group by子句、having子句)。update更新、delete删除、truncate截断。
文章目录
1、Create创建
1.1、insert
1.1.1、基本语法说明
SQL 中的 INSERT INTO
语句用于向表中插入新记录。可以有两种语句形式:
1、全列插入: 此情况下无需指定要插入数据的列名,只需提供被插入的值即可。需要注意插入的数据要按照创建表时字段的顺序排列数据。
INSERT INTO table_name VALUES (value1, value2 ,...);
2、指定列插入: 该形式可以指定列名及被插入的值。这种语句下不要求( column1, column2,...)
与表结构创建的顺序一致,但要求指定的 column 与 value 要一一对应。
INSERT INTO table_name ( column1, column2,...)VALUES (value1, value2 ,...);
参数说明:
table_name 要插入数据的表名称。
column1, column2, column3, ... 表中的列名
value1, value2, value3, ... 要插入的具体数值
如果数据是字符型,必须使用单引号 ' 或者双引号 ",如: 'value1', "value1"
如下,实则[]
中的字段可以省略:
INSERT [INTO] table_name
[(column [, column] ...)]
VALUES (value_list) [, (value_list)] ...
value_list: value, [, value] ...
1.1.2、单行数据插入+多行数据插入
插入单行数据:
插入多行数据:这里也可以分行写。
mysql> insert into a1 values
-> (10,'赵云','惊龙翔九霄,乱世中叱咤'),
-> (11,'周瑜','烽火连赤壁,东风乱敲打');
1.1.3、插入否则更新(on duplicate key update)
1)、相关引入
实际应用中经常会需要需要导入数据的场景。通常有两情况:①当导入的数据不存在,此时需要对其进行插入(添加);②当导入的数据存在时,此时需要修改更新。
对上述二者,一般思路是将其分为两块实现,①先查询判断数据是否存在表中;②在判断需要插入还是更新数据。
mysql中,ON DUPLICATE KEY UPDATE
语句可以做到对上述两个步骤一步到位。
场景举例:
如用户注册与登录。当前账号已经注册。
订单信息修改:若存在(更新)、若不存在(插入)
2)、语法说明
on duplicate key
:执行插入操作时的一个选项,允许在插入数据时,根据是否遇到重复键的情况,选择执行插入或更新操作。语法如下:
INSERT ... ON DUPLICATE KEY UPDATE
column = value [, column = value] ...
说明: 当在数据库中使用插入操作时,如果键值已经存在,会触发错误(通常由主键冲突、唯一键冲突引起)。若我们不想直接返回报错,可使用“on duplicate key”选项,定义遇到这种情况时要执行的操作。
结果说明:
0 row affected: 表中有冲突数据,但冲突数据的值和 update 的值相等。
1 row affected: 表中没有冲突数据,数据被插入。
2 row affected: 表中有冲突数据,并且数据已经被更新。
PS:需要注意的是,具体的语法和行为可能会因不同的数据库系统而有所差异。
3)、使用演示
演示没有使用duplicate key update时,数据存在冲突的情况:
演示使用duplicate key update后,返回的三种结果情况:
1.1.4、插入查询(其它:创建一个结构相同的表create table like)
1)、基本语法说明
插入查询: 在MySQL中,插入查询通常指的是将查询到的数据插入到数据库表中。语法如下:
INSERT INTO table_name [(column [, column ...])] SELECT ...
创建同结构的表: 在SQL中,CREATE TABLE … LIKE 语句用于复制一个现有表的结构,但不复制数据。 这意味着所创建出来的新表将具有与现有表相同的列、数据类型、约束等,但新表中不会有任何数据。语法如下:
CREATE TABLE new_table_name (LIKE old_table_name);
2)、案例演示:删除表中的的重复复记录,重复的数据只能有一份
演示如下:只需要对新表修改表名称即可。
一些使用到的语句如下:
mysql> create table a3_1( id int, name varchar(20) );
Query OK, 0 rows affected (0.04 sec)
mysql> insert into a3_1 values
-> (1,'aaa'),
-> (1,'aaa'),
-> (2,'bbb'),
-> (2,'bbb'),
-> (3,'ccc'),
-> (3,'ccc'),
-> (3,'ccc'),
-> (4,'ddd');
Query OK, 8 rows affected (0.01 sec)
Records: 8 Duplicates: 0 Warnings: 0
mysql> create table a3_2 like a3_1;
Query OK, 0 rows affected (0.04 sec)
mysql> insert into a3_2 select distinct * from a3_1;
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
其它说明:
1、这里like建表语句,是将原有结构原封不动复制过来:
2、实际上该插入查询语句可以直接作用于原表,即从自己表中查询到数据,再插入到表本身中(相当于插入了重复数据。)
1.2、replace
1)、语法说明
MySQL中的REPLACE
语句用于替换表中的记录。工作原理如下:
①如果表中找不到与新插入数据行匹配的值(主键 或者 唯一键 没有冲突),则执行标准 INSERT 语句。
②如果表中发现重复记录(主键 或者 唯一键 存在冲突),则先删除现有行,然后在表中插入新记录。
REPLACE INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...);
换句话说, REPLACE 语句中更新分两步执行。首先,它将删除现有记录,然后添加新更新的记录,类似于标准的 INSERT 命令。因此,我们可以说 REPLACE 语句执行两个标准函数,DELETE和INSERT。
2)、相关演示
使用演示如下,整体格式和insert没区别,可单行插入或多行插入,可全列插入或指定插入。
当然,若此处设置有多个唯一键,且存在多行起冲突时,affected的记录不止1~2行。但replace整体工作原理不变:它会先尝试插入新记录,如果存在唯一键或主键冲突,则会删除现有记录,然后插入新记录。
2、Retrieve读取
2.1、select 列(单表查询)
1)、语法说明
MySQL的SELECT语句是用来从数据库表中检索数据的。下面是SELECT语句的基本语法:
SELECT
[DISTINCT] {* | {column [, column] ...}
[FROM table_name]
[WHERE ...]
[ORDER BY column [ASC | DESC], ...]
LIMIT ...
在查询语句中,要求必须包含SELECT和FROM,其它都是可选项。以下是SELECT的使用及相关的组合关键字:
SELECT
后跟逗号分隔列或星号(*)列表,表示返回所有列。
FROM
指定要查询数据的表或视图。
JOIN
根据特定的连接条件从其他表中获取相关数据。
WHERE
子句过滤结果集中的行。
GROUP BY
子句将一组行分组到组中,并在每个组上应用聚合函数。
HAVING
子句根据GROUP BY子句定义的组过滤组。
ORDER BY
子句指定用于排序的列的列表。
LIMIT
约束返回的行数。
2.1.1、全列查询
相关语法:
SELECT * FROM table_name;
其它说明: 通常情况下不建议使用 *
进行全列查询。因为:①查询的列越多,意味着需要传输的数据量越大,且会存在刷屏问题(占用和浪费MySQL数据库服务器、产生不必要的I/O磁盘、浪费网络流量。);② 可能会影响到索引的使用。(索引待后续讲解)
2.1.2、指定列查询
相关语法:
SELECT column_name, column_name FROM table_name;
其它说明:指定列的顺序不需要按定义表的顺序来。
2.1.3、查询字段为表达式
1)、基本语法说明
SELECT语句后可跟随表达式,以对检索的数据进行计算或转换。
1、列表达式:可以使用列表达式来计算或转换列的值。 如,算术运算符(如加、减、乘、除)或函数(如CONCAT()、UPPER()、LOWER()等)来创建列表达式。
SELECT column1, column2 + 10, CONCAT(column3, ' ', column4)
FROM table_name;
2、常量表达式:可以在SELECT语句中使用常量表达式来指定一个常数值。 常量表达式可以是数字、字符串或日期。
SELECT 'Hello, World!' AS greeting, 12345 AS number, '2023-07-19' AS date
FROM table_name;
3、条件表达式:可以使用条件表达式(也称为布尔表达式)来筛选满足特定条件的行。 条件表达式由比较运算符(如等于、不等于、大于、小于等)、逻辑运算符(如AND、OR)和括号组成。
SELECT column1, column2
FROM table_name
WHERE column1 > 10 AND column2 = 'value';
4、聚合函数:聚合函数用于对多行数据进行计算,并返回单个值。 常见的聚合函数包括COUNT()、SUM()、AVG()、MIN()和MAX()等。
SELECT COUNT(*) AS total_rows, SUM(column1) AS total_value
FROM table_name;
5、等等。
PS:这里的表达式可以结合实际需求而定,设置成有意义的属性列操作。比如两科乘积之和、销售净额统计,等等此类与实际生活有关。
2)、相关演示
演示select语句本身就支持表达式:
演示select和表格结合使用查询:
2.1.4、为查询结果起别名(列别名)
1)、MySQL中的两种别名:列别名和表别名
别名可以提高查询的可读性,MySQL支持两种别名,称为列别名和表别名。
列别名: 有时列的名称很是一个表达式、不太好理解、输入麻烦等各种因素,为了查询方便,可以为列提供描述性名称,即列别名。用法如下:
SELECT
[column_1 | expression] [AS] descriptive_name #要给列添加别名,可以使用AS关键词后跟别名。
FROM table_name;
SELECT ---别名中包含空格,必须引用
[column_1 | expression] [AS] 'descriptive name' #因为AS关键字是可选的,可以在语句中省略它。
FROM table_name;
PS:在MySQL中,可以使用ORDER BY
,GROUP BY
和HAVING
子句中的列别名来引用该列。
2)、列别名使用演示
注意事项:select语句后面可以跟随很多选项,其执行有一定顺序。对于as列别名,一般不能在WHERE子句中使用,因MySQL评估求值WHERE子句时,SELECT子句中指定的列的值可能尚未确定。
2.1.5、去重查询(distinct )
1)、基本语法说明
SELECT DISTINCT
语句用于返回唯一的不同的记录。一个列可能会包含多个重复值,若仅需要列出不同 ( distinct ) 的值,可以使用该语句:
SELECT DISTINCT column_name , column_name FROM table_name;
一些举例:
1、DISTINCT 多列: DISTINCT 子句可以与多个列一起使用。在这种情况下,MySQL使用这些列中的值组合来确定结果集中行的唯一性。
2、DISTINCT 和 NULL值: 如果字段中有NULL值并且要对该列使用DISTINCT 子句,则MySQL仅保留一个NULL值,因为DISTINCT 子句将所有NULL值视为相同的值。
3、DISTINCT和聚合函数: 可以将DISTINCT子句与聚合函数(例如,SUM,AVG和COUNT )一起使用,将聚合函数应用于结果集之前删除重复的行。
4、DISTINCT 和 LIMIT子句: 如果将DISTINCT 子句与LIMIT子句一起使用,MySQL会在找到LIMIT子句中指定的唯一行数时立即停止搜索。
2)、相关演示
可根据需要加上其它选项:
2.1.6、按条件筛选(where)
MySQL中,SELECT语句经常与WHERE子句结合使用,以便根据指定的条件筛选结果。WHERE子句允许你定义搜索条件,从而只检索满足这些条件的行。
即下述2.2介绍内容。
2.2、where 子句
SQL WHERE 子句用于筛选出那些满足指定条件的记录:
SELECT column_name(s) FROM table_name WHERE column_name operator value;
2.2.1、比较运算符
2.2.2.1、汇总
运算符 | 说明 |
---|---|
>, >=, <, <= | 大于,大于等于,小于,小于等于 |
= | 等于,NULL 不安全,例如 NULL = NULL 的结果是 NULL |
<=> | 等于,NULL 安全,例如 NULL <=> NULL 的结果是 TRUE(1) |
!=, <> | 不等于 |
BETWEEN a0 AND a1 | 范围匹配,[a0, a1],如果 a0 <= value <= a1,返回 TRUE(1) |
IN (option, …) | 如果是 option 中的任意一个,返回 TRUE(1) |
IS NULL | 是 NULL |
IS NOT NULL | 不是 NULL |
LIKE | 模糊匹配。% 表示任意多个(包括 0 个)任意字符;_ 表示任意一个字符 |
2.2.2.2、>, >=, <, <=
一个区别说明: 在MySQL中,SELECT语句用于从数据库表中检索数据,而WHERE子句用于筛选符合特定条件的行。
①若直接在SELECT语句中使用表达式时,它将在每一行上进行计算,并返回一个结果。
②若在WHERE子句中使用表达式时,它将对表中的行进行筛选,只返回满足条件的行。
其它一些演示例子: 实则这里有一个select子句执行顺序的说明,后续会简要介绍到。
2.2.2.3、=、<=>、IS NULL、IS NOT NULL
关于NULL值的补充说明: NULL一般不参与计算。若要筛选出NULL,可使用<=>
NULL、或者 IS NULL
、IS NOT NULL
。
官网描述:
The NULL value can be surprising until you get used to it. Conceptually, NULL means “a missing unknown value” and it is treated somewhat differently from other values.
解决方式是使用 <=> 来进行等值比较:
NULL-safe equal. This operator performs an equality comparison like the = operator, but returns 1 rather than NULL if both operands are NULL, and 0 rather than NULL if one operand is NULL.
说明: 在习惯之前,NULL 值可能会让人感到惊讶。从概念上讲,NULL 意味着 “丢失的未知值”,其处理方式与其他值有些不同。NULL 是安全的判等运算符。该运算符与=
运算符一样执行相等比较,但如果两个操作数都是 NULL,则返回 1 而不是 NULL;如果一个操作数是 NULL,则返回 0 而不是 NULL。
演示如下:
实则判断NULL可以使用IS NULL
和IS NOT NULL
:
2.2.2.4、!=, <>
说明: 在MySQL中,!=
和 <>
是用于比较两个值是否不相等的运算符。选择使用 != 或 <> 运算符取决于个人偏好和代码的可读性。
相关演示如下:
2.2.2.5、BETWEEN a0 AND a1
说明: SQL 的BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。但需要注意,不同的数据库中,BETWEEN 操作符会产生不同的结果:[a0,a1]
、(a0,a1)
、[a0,a1)
。
SELECT column_name FROM table_name WHERE column_name BETWEEN value1 AND value2;
演示如下:
2.2.2.6、IN (option, …)
1)、基本语法说明
IN 运算符用于确定一个指定的值是否在一组值匹配的任何值或子查询。 以下IN 运算符的语法:
SELECT column1,column2,...
FROM
table_name
WHERE
(expr|column_1) IN ('value1','value2',...);
IN运算符逻辑: 若(expr|column_1)
在指定列表('value1','value2',...)
中,则返回1 ;若不在,则返回0。
当列表中的值都是常量时,MySQL执行以下步骤:
首先,评估基于所述值类型的的column_1所述的或expr 表达的结果 。
其次,对值进行排序。
第三,使用二进制搜索算法搜索值。因此,使用IN 运算符查询执行带有常量列表的速度非常快。
注意事项:
1、如果expr列表中的任何值NULL,则IN 运算符返回NULL。
2、IN运算符与NOT运算符组合,可以用于检查值是否与列表或子查询中的任何值不匹配。也可以其它语句中在WHERE子句中使用IN运算符,例如 UPDATE,和DELETE。
2)、相关演示
演示结果如下:
2.2.2.7、LIKE模糊匹配
1)、基本语法说明
SQL 中的 LIKE 子句用于在 WHERE 子句中搜索列中的指定模式。使用该子句时通常与OR或AND运算符结合使用,以根据多个模式过滤结果。
SELECT column_name(s) FROM table_name WHERE column_name LIKE pattern;
pattern
是一个合法的模式字符串,有很多种 模式,通常与两个通配符一起使用:%
和 _
。
%
:代表零个、一个或多个字符。
_
:代表一个单一的字符。
2)、相关演示
1、MySQL LIKE 使用百分比(%)通配符: ①百分号 ( % ) 可以代替任何任意数量的字符;②%在模式pattern
的开头、结尾、中间任意位置都可以使用。
匹配时,一般是不区分大小写的,但是根据MySQL的配置方式,加BINARY
关键字,搜索时会区分大小写。
SELECT column_name(s) FROM table_name WHERE BINARY column_name LIKE pattern;
2、MySQL LIKE使用下划线(_)通配符: 与%能匹配0个字符不一样,_
总是匹配一个字符,不能多也不能少。
3、MySQL LIKE和NOT运算符: MySQL可以使用NOT运算符与LIKE运算符组合以查找与特定模式不匹配的字符串。
2.2.2、逻辑运算符
2.2.2.1、汇总
1)、基本说明
运算符 | 说明 |
---|---|
AND | 多个条件必须都为 TRUE(1),结果才是 TRUE(1) |
OR | 任意一个条件为 TRUE(1), 结果为 TRUE(1) |
NOT | 条件为 TRUE(1),结果为 FALSE(0) |
说明: SQL 中的 AND 或 OR 运算符用于基于一个以上的条件对记录进行过滤。可以把 AND 和 OR 结合起来 (使用圆括号来组成复杂的表达式)。
2)、逻辑运算符短路情况说明
由于逻辑运算符(如AND、OR)可以组合使用,和C语言一样,使用时可能会发生所谓的 “短路”现象 ,这意味着某些条件的计算可能会被跳过,取决于运算符的优先级和给定的表达式结构。
AND 运算符的短路行为: 当使用 AND 连接多个条件时,如果第一个条件为 FALSE,则整个表达式的结果已经确定为 FALSE,后续的条件将不会被评估。
OR 运算符的短路行为: 当使用 OR 连接多个条件时,如果第一个条件为 TRUE,则整个表达式的结果已经确定为 TRUE,后续的条件将不会被评估。
3)、逻辑运算符优先级
在MySQL中,逻辑运算符的优先级遵循标准的逻辑运算优先级规则,其中AND运算符(AND/&&)具有较高的优先级,而OR运算符(OR/||)具有较低的优先级。这意味着在逻辑表达式中,AND运算符的优先级高于OR运算符。
2.2.3、理解select执行时的顺序流程(重点之一)
1)、基本说明
问题: 如何理解mysql在执行select语句时,各子句之间的执行顺序?
说明: 在MySQL中,SELECT语句的执行顺序并不完全按照我们在SQL语句中书写的顺序进行。 以下是SELECT语句的典型执行顺序:
1、FROM 和 JOIN
:MySQL首先解析FROM子句中提到的所有表,并处理JOIN操作。这是查询的核心部分,涉及多表查询时尤为重要。
2、WHERE
:接下来,MySQL应用WHERE子句中的条件来过滤结果集。这一步会排除不满足条件的记录,减少后续操作的数据量。
3、GROUP BY
:如果存在GROUP BY子句,MySQL会根据指定的列对结果集进行分组。这一步通常与聚合函数(如COUNT、SUM、AVG等)一起使用,对分组后的数据进行处理。
4、HAVING
:在GROUP BY之后,HAVING子句中的条件应用于已分组的记录。HAVING子句通常用于过滤分组后的结果,与WHERE子句在分组前的过滤有所不同。
5、SELECT
:在此阶段,MySQL选择需要的列,并进行任何指定的计算或函数操作。SELECT子句决定了最终返回哪些列和如何格式化这些列。
6、DISTINCT
:DISTINCT关键字用于消除结果集中的重复行。它通常在SELECT子句之后应用,确保每个记录都是唯一的。
7、ORDER BY
:如果存在ORDER BY子句,MySQL会根据指定的列对结果集进行排序。注意:尽管在执行顺序中排在前面,但在实际的逻辑处理中,ORDER BY是在所有其他操作之后进行的。排序操作可能非常消耗资源,因此优化这部分至关重要。
8、LIMIT / OFFSET
:最后,LIMIT和OFFSET子句用于限制返回的记录数量。这通常用于分页查询,只返回特定范围的记录。
9、返回结果
:MySQL将最终的结果集返回给客户端。在这一步,结果以适当的格式呈现给用户或应用程序。
理解这个执行顺序有助于更好地优化查询性能,因为某些操作(如过滤和分组)可能比其他操作(如选择和排序)更消耗资源。通过调整查询的结构、使用索引或进行其他优化措施,可以显著提高查询性能。
2)、举例说明
以查询出数学成绩大于80分的记录(select id,name,math from a2 where math>80;
)为例,根据上述讲述可知:
以查找总成绩小于240的记录为例(select name,chinese+math+english as total from a2 where chinese+math+english<240;
):解释起别名时为什么报错。
2.3、order 结果排序
2.3.1、语法说明
1)、默认状态
默认情况下, 使用SELECT语句从表中查询数据时,结果集不按任何顺序排序。(未定义行为)
PS:实际只需要记住执行SELECT查询时,如果没有使用ORDER BY子句来明确指定排序顺序,那么返回的结果的顺序是不确定的。 (即每次执行相同的查询可能会得到不同的结果,除非表中的数据本身有某种自然顺序)。
存在一些常见的情况:(补充了解)
①没有ORDER BY,但存在主键的情况下:对于有主键的表,MySQL通常会按照主键的顺序返回结果。但这并不是一个保证,因为存储引擎的具体实现可能会有所不同。尽管如此,在实际应用中,许多开发者都发现查询结果似乎是按照主键顺序返回的。
②没有ORDER BY,也没有主键的情况下:结果集的顺序是不确定的。MySQL不会按照任何特定的顺序返回结果,除非表中的数据本身有某种自然顺序(例如,按照插入顺序或更新顺序)。
2)、order by排序状态
如果要对结果集进行排序,请使用该ORDER BY 子句。ORDER BY 允许的操作:
①按单列或多列对结果集进行排序。
②按升序或降序对不同列的结果集进行排序。
相关语法:
SELECT column1, column2,...
FROM tbl
ORDER BY column1 [ASC|DESC], column2 [ASC|DESC],...
ASC
:升序 DESC
:下降
默认情况下,ORDER BY 如果未指定ASC或DESC 显式,则子句按升序对结果集进行排序 。
2.3.2、相关演示
2.3.2.1、单列排序(正序、逆序)
说明:这里的排序不是单独只对某列进行排序,而是以其为key值,对记录与记录之间整行进行排序变动。
2.3.2.2、对于NULL值、字符串(补充了解)
1)、使用ORDER BY对字符串进行排序
概述: MySQL中,使用ORDER BY对字符串进行排序时,排序是基于字符的字典顺序(lexicographical order)进行的。这意味着字符串将按照每个字符的ASCII或Unicode值进行排序,具体取决于字符集和校对规则(collation)。
一些要点:
默认排序规则: 如果不指定特定的校对规则,MySQL将使用表的默认校对规则进行排序。 对于ASCII字符集,排序通常是按照字符的ASCII码值进行的。对于Unicode字符集(如utf8或utf8mb4),排序是按照Unicode码点进行的。
大小写敏感性: 默认情况下,字符串的排序是大小写敏感的。这意味着大写字母和小写字母会被视为不同的字符。如果需要执行大小写不敏感的排序,可以使用UPPER()
或LOWER()
函数将字符串转换为统一的大小写形式,然后再进行排序。
特殊字符和空格: 特殊字符和空格在排序时也会被考虑。例如,字符串"apple"和"apple "(后面有一个空格)会被视为不同的字符串。如果需要忽略字符串末尾的空格进行排序,可以使用TRIM()
函数去除字符串两端的空格。
举例演示:
2、MySQL中,使用ORDER BY排序时,如果是升序,NULL值会出现在最前面;如果是降序,NULL值会出现在最后。(因此,若想改变NULL值的排序行为,可以使用IS NULL或IS NOT NULL条件进行调整)
2.3.2.3、多列排序(升序、降序)
说明:多列排序,可用,
分隔开,排序优先级随书写顺序。若当前列相等,则满足后续列排序需求。
2.4、limit 子句
2.4.1、基本使用介绍
1)、语法说明
SELECT语句中使用LIMIT 子句可以约束结果集中的行数。LIMIT子句接受一个或两个参数,两个参数的值必须为零或正整数。 以下说明了LIMIT带有两个参数的子句语法:
SELECT
column1,column2,...
FROM
table
LIMIT offset , count;
其中,通过指定适当的offset和count值,可以控制查询结果的返回范围:
offset
可以理解为要跳过的行数,实则是偏移量的含义。(offset指定要返回的第一行的偏移量,初始行的偏移量是0(不是1),该选项是可选的)
count
表示要返回的最大行数。
如下,若省略offset,则表示从起始位置开始统计count数目的记录:
SELECT
select_list
FROM
table
LIMIT count;
其查询等效于以下offset=0:
SELECT
select_list
FROM
table
LIMIT 0 , count;
2)、相关演示
使用演示:
执行顺序说明:
2.4.2、分页筛选
语法介绍: 在MySQL中,分页筛选是一种常见的操作,用于从数据库中检索特定范围的数据。其主要依赖于LIMIT和OFFSET子句来实现,LIMIT用于限制返回的记录数,而OFFSET用于指定从哪一行开始返回记录。
-- 起始下标为 0
-- 从 0 开始,筛选 n 条结果
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n;
-- 从 s 开始,筛选 n 条结果
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT s, n;
-- 从 s 开始,筛选 n 条结果,比第二种用法更明确,建议使用
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n OFFSET s;
PS:对未知表进行查询时,最好加一条 LIMIT 1,避免因为表中数据过大,查询全表数据导致数据库卡死。
演示结果如下:
实际应用举例: Web应用程序。在Web应用程序中,用户通常需要浏览分页显示的数据。通过使用分页筛选,应用程序可以按需从数据库中检索数据,并在页面上展示给用户。例如,社交媒体平台可能会使用分页筛选来展示用户动态或帖子,每个页面包含一定数量的记录。
3、Update更新
3.1、update
3.1.1、基本介绍
语法如下:
UPDATE [LOW_PRIORITY] [IGNORE] table_name
SET
column = expr [, column = expr ...]
[WHERE ...] [ORDER BY ...] [LIMIT ...]
table_name
指明需要更新数据的表名。
SET子句
:指定要更新的列及其对应的新值。若有多个列需要更新,使用逗号分隔。
WHERE子句
:指定更新的条件,确定哪些记录需要更新。WHERE子句是可选项,如果省略,UPDATE语句将更新表中的所有行。
UPDATE语句中支持两个修饰符:
LOW_PRIORITY
:使用 LOW_PRIORITY 修饰符时,如果该表上有其他的查询(例如读查询或写查询)正在运行,那么这些查询会先于 UPDATE 语句执行。
IGNORE
:使用 IGNORE 修饰符时,如果在 UPDATE 语句执行过程中遇到任何错误,MySQL 将忽略这些错误并继续执行。
3.1.2、相关演示
演示修改单行(单行单列、单行多列):
演示修改多行(多行单列、多行多列):
演示全表更新:
4、Delete删除
4.1、delete
4.1.1、基本介绍
MySQL中,DELETE语句用于从数据库表中删除记录:
DELETE FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]
table_name
:指定从中删除数据的表。
WHERE子句
:可以指定删除符合条件的行。PS:WHERE子句是可选项,如果省略WHERE子句,DELETE语句将删除表中的所有行。
返回:除了从表中删除数据外,DELETE语句还返回已删除的行数。
4.1.2、相关演示
一些说明:使用DELETE语句删除表中的数据时,自增(AUTO_INCREMENT)字段的值不会自动重置或清空。
4.2、truncate截断表
4.2.1、基本介绍
1)、基本语法说明
说明:MySQL中,TRUNCATE TABLE语句允许删除表中的所有数据。就功能而言,TRUNCATE TABLE语句类似于没有WHERE子句的DELETE语句。但在某些情况下,其比DELETE语句更有效。
TRUNCATE [TABLE] table_name
TABLE关键字:可选项。
注意事项:
1、如果表具有AUTO_INCREMENT列,则TRUNCATE TABLE语句将自动递增值重置为零。
2、此外,TRUNCATE TABLE语句不使用DELETE语句,因此与表关联的DELETE触发器将不被调用。(TRUNCATE在删除数据的时候,并不经过真正的事物,所以无法回滚)
2)、一些补充
如果使用的是InnoDB表,MySQL将在删除数据之前检查表中是否有可用的外键约束。 以下是一些情况:
- 如果表具有任何外键约束,则TRUNCATE TABLE语句会逐个删除行。如果外键约束具有DELETE CASCADE动作,则子表中的相应行也将被删除。如果外键约束没有指定DELETE CASCADE动作,则TRUNCATE TABLE将逐个删除行,并且遇到由子表中的行引用的行时,它将停止并发出错误。
- 如果表没有任何外键约束,则TRUNCATE TABLE语句将删除该表并重新创建一个具有相同结构的新表,这比使用DELETE语句特别是对于大表更快更有效。
如果使用其他存储引擎,则TRUNCATE TABLE语句将删除并重新创建一个新表。
4.2.2、相关演示
5、group by子句、having子句
说明:聚合函数见MySQL函数章节的博文。
5.1、基本介绍
1)、对group by子句
MySQL中,GROUP BY 语句根据一个或多个列对结果集进行分组,一般配合聚合函数使用(如SUM,AVG,MAX,MIN,COUNT等)。
SELECT
c1, c2,..., cn, aggregate_function(ci)
FROM
table
WHERE
where_conditions
GROUP BY c1 , c2,...,cn;
PS:
1、标准SQL不允许在GROUP BY子句中使用别名,但MySQL支持此功能。
2、在GROUP BY子句中,可以使用DESC或 ASC 对获得的分组进行排序。
3、使用GROUP BY子句时,SELECT子句中的列必须是在GROUP BY子句中指定的列或者是用于聚合的列。
4、在GROUP BY操作中,NULL值通常会被视为一个独立的组。 也就是说,所有NULL值都会被单独列出来,并且对NULL值的聚合函数计算也是独立的。
2)、对having子句
HAVING子句通常与GROUP BY 子句一起使用,以根据指定的条件过滤组。 如果GROUP BY省略HAVING子句,则子句的行为类似于WHERE 子句。
3)、WHERE和HAVING的对比
WHERE子句用于在数据分组之前对数据集进行筛选。它基于指定的条件过滤记录,并返回满足条件的行。
HAVING子句用于在数据分组之后对聚合结果进行筛选。它允许你基于聚合函数的结果(如COUNT、SUM、AVG等)对组进行过滤。
几个关键区别:
应用阶段:WHERE子句在数据聚合之前应用条件,而HAVING子句在数据聚合之后应用条件。
适用范围:WHERE子句适用于单个行的筛选,而HAVING子句适用于聚合结果的筛选。
聚合函数的使用:WHERE子句不能与聚合函数一起使用,而HAVING子句可以与聚合函数一起使用。
NULL值的处理:在WHERE子句中,NULL值可能导致条件评估为FALSE或UNKNOWN,而在HAVING子句中,NULL值通常被视为一个独立的组。
5.2、使用演示
5.2.1、使用的数据
演示使用的雇员信息表来自oracle 9i的经典测试表:
EMP:员工表
DEPT:部门表
SALGRADE:工资等级表
5.2.1.1、dept部门表
dept部门表 结构、数据如下:
mysql> desc dept;
+--------+--------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------------------+------+-----+---------+-------+
| deptno | int(2) unsigned zerofill | NO | | NULL | |
| dname | varchar(14) | YES | | NULL | |
| loc | varchar(13) | YES | | NULL | |
+--------+--------------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> show create table dept \G;
*************************** 1. row ***************************
Table: dept
Create Table: CREATE TABLE `dept` (
`deptno` int(2) unsigned zerofill NOT NULL COMMENT '部门编号',
`dname` varchar(14) DEFAULT NULL COMMENT '部门名称',
`loc` varchar(13) DEFAULT NULL COMMENT '部门所在地点'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> select * from dept;
+--------+------------+----------+
| deptno | dname | loc |
+--------+------------+----------+
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |
+--------+------------+----------+
4 rows in set (0.00 sec)
5.2.1.2、salgrade薪资表
salgrade薪资表 结构、数据如下:
mysql> desc salgrade;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| grade | int(11) | YES | | NULL | |
| losal | int(11) | YES | | NULL | |
| hisal | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> show create table salgrade \G;
*************************** 1. row ***************************
Table: salgrade
Create Table: CREATE TABLE `salgrade` (
`grade` int(11) DEFAULT NULL COMMENT '等级',
`losal` int(11) DEFAULT NULL COMMENT '此等级最低工资',
`hisal` int(11) DEFAULT NULL COMMENT '此等级最高工资'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> select * from salgrade;
+-------+-------+-------+
| grade | losal | hisal |
+-------+-------+-------+
| 1 | 700 | 1200 |
| 2 | 1201 | 1400 |
| 3 | 1401 | 2000 |
| 4 | 2001 | 3000 |
| 5 | 3001 | 9999 |
+-------+-------+-------+
5 rows in set (0.00 sec)
5.2.1.3、emp员工表
emp员工表 结构、数据如下:
mysql> desc emp;
+----------+--------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------------------+------+-----+---------+-------+
| empno | int(6) unsigned zerofill | NO | | NULL | |
| ename | varchar(10) | YES | | NULL | |
| job | varchar(9) | YES | | NULL | |
| mgr | int(4) unsigned zerofill | YES | | NULL | |
| hiredate | datetime | YES | | NULL | |
| sal | decimal(7,2) | YES | | NULL | |
| comm | decimal(7,2) | YES | | NULL | |
| deptno | int(2) unsigned zerofill | YES | | NULL | |
+----------+--------------------------+------+-----+---------+-------+
8 rows in set (0.00 sec)
mysql> show create table emp \G;
*************************** 1. row ***************************
Table: emp
Create Table: CREATE TABLE `emp` (
`empno` int(6) unsigned zerofill NOT NULL COMMENT '雇员编号',
`ename` varchar(10) DEFAULT NULL COMMENT '雇员姓名',
`job` varchar(9) DEFAULT NULL COMMENT '雇员职位',
`mgr` int(4) unsigned zerofill DEFAULT NULL COMMENT '雇员领导编号',
`hiredate` datetime DEFAULT NULL COMMENT '雇佣时间',
`sal` decimal(7,2) DEFAULT NULL COMMENT '工资月薪',
`comm` decimal(7,2) DEFAULT NULL COMMENT '奖金',
`deptno` int(2) unsigned zerofill DEFAULT NULL COMMENT '部门编号'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> select * from emp;
+--------+--------+-----------+------+---------------------+---------+---------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+--------+--------+-----------+------+---------------------+---------+---------+--------+
| 007369 | SMITH | CLERK | 7902 | 1980-12-17 00:00:00 | 800.00 | NULL | 20 |
| 007499 | ALLEN | SALESMAN | 7698 | 1981-02-20 00:00:00 | 1600.00 | 300.00 | 30 |
| 007521 | WARD | SALESMAN | 7698 | 1981-02-22 00:00:00 | 1250.00 | 500.00 | 30 |
| 007566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL | 20 |
| 007654 | MARTIN | SALESMAN | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 | 30 |
| 007698 | BLAKE | MANAGER | 7839 | 1981-05-01 00:00:00 | 2850.00 | NULL | 30 |
| 007782 | CLARK | MANAGER | 7839 | 1981-06-09 00:00:00 | 2450.00 | NULL | 10 |
| 007788 | SCOTT | ANALYST | 7566 | 1987-04-19 00:00:00 | 3000.00 | NULL | 20 |
| 007839 | KING | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 | NULL | 10 |
| 007844 | TURNER | SALESMAN | 7698 | 1981-09-08 00:00:00 | 1500.00 | 0.00 | 30 |
| 007876 | ADAMS | CLERK | 7788 | 1987-05-23 00:00:00 | 1100.00 | NULL | 20 |
| 007900 | JAMES | CLERK | 7698 | 1981-12-03 00:00:00 | 950.00 | NULL | 30 |
| 007902 | FORD | ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL | 20 |
| 007934 | MILLER | CLERK | 7782 | 1982-01-23 00:00:00 | 1300.00 | NULL | 10 |
+--------+--------+-----------+------+---------------------+---------+---------+--------+
14 rows in set (0.00 sec)
5.2.2、单列分组:显示每个部门的平均工资和最高工资
演示如下:
5.2.3、多列分组:显示每个部门的每种岗位的平均工资和最低工资
演示如下:
5.2.4、having子句使用:显示平均工资低于2000的部门和它的平均工资
演示如下: