文章目录

  • 操作数据表
  • 1、SELECT:查询数据表
  • 2、DISTINCT:过滤重复数据
  • 3、AS:设置别名
  • 4、LIMIT:限制查询结果的条数
  • 5、ORDER BY:对查询结果排序
  • 6、WHERE:条件查询语句
  • 7、LIKE:模糊查询(匹配)
  • 8、 IS NULL:空值查询
  • 9、GROUP By:分组查询
  • 10、HAVING:过滤分组
  • 11、多表查询(交叉连接、内连接、外连接)
  • 11.1、笛卡尔积
  • 11.2、 交叉连接
  • 11.3、内连接
  • 11.4 、外连接
  • 12、MySQL子表查询(嵌套查询)
  • 12.1、子表查询的使用
  • 12.2、子查询语句的位置(注意事项)
  • 13、REGEXP:正则表达式匹配(同java...)
  • 14、INSERT:插入数据
  • 15、UPDATE:修改数据
  • 16、DELETE:删除数据
  • 17、TRUNCATE:清空表记录
  • 17.1、语法
  • 17.2、TRUNCATE 和 DELETE 的区别
  • 18、MySQL如何处理无效数据值?


操作数据表

1、SELECT:查询数据表

在 MySQL 中,可以使用 SELECT 语句来查询数据。查询数据是指从数据库中根据需求,使用不同的查询方式来获取不同的数据,是使用频率最高、最重要的操作。
语法

SELECT
{* | <字段列名>}
[
FROM <表 1>, <表 2>…
[WHERE <表达式>
[GROUP BY <group by definition>
[HAVING <expression> [{<operator> <expression>}…]]
[ORDER BY <order by definition>]#如按照某列升序,写列名
[LIMIT[<offset>,] <row count>]
]

其中,各条子句的含义如下:

  • {*|<字段列名>}:包含星号通配符的字段列表,表示所要查询字段的名称。
  • <表 1>,<表 2>…,表 1 和表 2 表示查询数据的来源,可以是单个或多个。
  • WHERE <表达式>是可选项,如果选择该项,将限定查询数据必须满足该查询条件。
  • GROUP BY< 字段 >,该子句告诉 MySQL 如何显示查询出来的数据,并按照指定的字段分组。
  • [ORDER BY< 字段 >],该子句告诉 MySQL 按什么样的顺序显示查询出来的数据,可以进行的排序有升序(ASC)和降序(DESC),默认情况下是升序。
  • [LIMIT[,]],该子句告诉 MySQL 每次显示查询出来的数据条数。

实例

mysql 表记录类似rowid mysql 操作数据记录_mysql

2、DISTINCT:过滤重复数据

在 MySQL 中使用 SELECT 语句执行简单的数据查询时,返回的是所有匹配的记录。如果表中的某些字段没有唯一性约束,那么这些字段就可能存在重复值。为了实现查询不重复的数据,MySQL 提供了 DISTINCT 关键字。

DISTINCT 关键字的主要作用就是对数据表中一个或多个字段重复的数据进行过滤,只返回其中的一条数据给用户。

DISTINCT 关键字的语法格式为:

SELECT DISTINCT <字段名> FROM <表名>;

其中,“字段名”为需要消除重复记录的字段名称,多个字段时用逗号隔开。
使用 DISTINCT 关键字时需要注意以下几点:

  • DISTINCT 关键字只能在 SELECT 语句中使用。
  • 在对一个或多个字段去重时,DISTINCT 关键字必须在所有字段的最前面。
  • 如果 DISTINCT 关键字后有多个字段,则会对多个字段进行组合去重,也就是说,只有多个字段组合起来完全是一样的情况下才会被去重

实例

mysql 表记录类似rowid mysql 操作数据记录_mysql 表记录类似rowid_02

因为 DISTINCT 只能返回它的目标字段,而无法返回其它字段,所以在实际情况中,我们经常使用 DISTINCT 关键字来返回不重复字段的条数。

3、AS:设置别名

为表指定别名的基本语法格式为:

<表名> [AS] <别名>
  • <表名>:数据库中存储的数据表的名称。
  • <别名>:查询时指定的表的新名称。
  • AS关键字可以省略,省略后需要将表名和别名用空格隔开。

注意:表的别名不能与该数据库的其它表同名字段的别名不能与该表的其它字段同名在条件表达式中不能使用字段的别名,否则会出现“ERROR 1054 (42S22): Unknown column”这样的错误提示信息。

为字段指定别名的基本语法格式为:

<字段名> [AS] <别名>
  • <字段名>:为数据表中字段定义的名称。
  • <字段别名>:字段新的名称。
  • AS关键字可以省略,省略后需要将字段名和别名用空格隔开。

4、LIMIT:限制查询结果的条数

当数据表中有上万条数据时,一次性查询出表中的全部数据会降低数据返回的速度,同时给数据库服务器造成很大的压力。这时就可以用 LIMIT 关键字来限制查询结果返回的条数。

LIMIT 是 MySQL 中的一个特殊关键字,用于指定查询结果从哪条记录开始显示,一共显示多少条记录。

LIMIT 关键字有 3 种使用方式,即指定初始位置、不指定初始位置以及与 OFFSET 组合使用。
实际上可以归纳为如下表格:

方式

语法

等价

参数局限

①指定初始位置

limit 记录起始下标 记录条数


LIMIT 后的两个参数必须都是自然数。

②不指定初始位置

limit 记录条数

①limit 0 记录条数

LIMIT 后的参数必须都是自然数。

③与OFFSET组合使用

limit 记录条数 OFFSET 记录起始下标

① limit 记录起始下标 记录条数

LIMIT 后的两个参数必须都是自然数。

实例:

mysql 表记录类似rowid mysql 操作数据记录_sql_03

5、ORDER BY:对查询结果排序

通过条件查询语句可以查询到符合用户需求的数据,但是查询到的数据一般都是按照数据最初被添加到表中的顺序来显示。为了使查询结果的顺序满足用户的要求,MySQL 提供了 ORDER BY 关键字来对查询结果进行排序。

在实际应用中经常需要对查询结果进行排序,比如,在网上购物时,可以将商品按照价格进行排序;在医院的挂号系统中,可以按照挂号的先后顺序进行排序等。

ORDER BY 关键字主要用来将查询结果中的数据按照一定的顺序进行排序。其语法格式如下:

ORDER BY <字段名> [ASC|DESC]
  • 字段名:表示需要排序的字段名称,多个字段时用逗号隔开。
  • ASC|DESC:ASC表示字段按升序排序;DESC表示字段按降序排序。其中ASC为默认值。

使用 ORDER BY 关键字应该注意以下几个方面:

  • ORDER BY 关键字后可以跟子查询
  • 当排序的字段中存在空值时,ORDER BY 会将该空值作为最小值来对待。
  • ORDER BY 指定多个字段进行排序时,MySQL 会按照字段的顺序从左到右依次进行排序。
  • 分为单字段排序和多字段排序
    实例:

6、WHERE:条件查询语句

语法:

select 字段 from 表名 where 逻辑表达式(查询条件);

mysql 表记录类似rowid mysql 操作数据记录_mysql_04

当然也可以配合Like使用

7、LIKE:模糊查询(匹配)

在 MySQL 中,LIKE 关键字主要用于搜索匹配字段中的指定内容。其语法格式如下:

[NOT] LIKE  '字符串'

其中:

  • NOT :可选参数,字段中的内容与指定的字符串不匹配时满足条件。
  • 字符串:指定用来匹配的字符串。“字符串”可以是一个很完整的字符串,也可以包含通配符。

LIKE 关键字支持百分号“%”和下划线“_”通配符。

通配符是一种特殊语句,主要用来模糊查询。当不知道真正字符或者懒得输入完整名称时,可以使用通配符来代替一个或多个真正的字符。

实例:

mysql 表记录类似rowid mysql 操作数据记录_mysql_05


区分大小写和使用反转义匹配字段中的转义字符

mysql 表记录类似rowid mysql 操作数据记录_oracle_06

8、 IS NULL:空值查询

MySQL 提供了 IS NULL 关键字,用来判断字段的值是否为空值(NULL)。空值不同于 0,也不同于空字符串。

如果字段的值是空值,则满足查询条件,该记录将被查询出来。如果字段的值不是空值,则不满足查询条件。

使用 IS NULL 的基本语法格式如下:

IS [NOT] NULL

其中,“NOT”是可选参数,表示字段值不是空值时满足条件。

实例:

mysql 表记录类似rowid mysql 操作数据记录_mysql 表记录类似rowid_07

9、GROUP By:分组查询

四种使用方式:

  • Group By 单独使用
  • 与Group_CONCAT()一起使用
  • 与聚合函数一起使用,sum,count,max,min
  • 与with rollup关键字使用

10、HAVING:过滤分组

在 MySQL 中,可以使用 HAVING 关键字对分组后的数据进行过滤。

使用 HAVING 关键字的语法格式如下:

HAVING <查询条件>

HAVING 关键字和 WHERE 关键字都可以用来过滤数据,且 HAVING 支持 WHERE 关键字中所有的操作符和语法。

但是 WHERE 和 HAVING 关键字也存在以下几点差异:

  • 一般情况下,WHERE 用于过滤数据行,而 HAVING 用于过滤分组。
  • WHERE 查询条件中不可以使用聚合函数,而 HAVING 查询条件中可以使用聚合函数。
  • WHERE 在数据分组前进行过滤,而 HAVING 在数据分组后进行过滤 。
  • WHERE 针对数据库文件进行过滤,而 HAVING 针对查询结果进行过滤。也就是说,WHERE 根据数据表中的字段直接进行过滤,而 HAVING 是根据前面已经查询出的字段进行过滤。
  • WHERE 查询条件中不可以使用字段别名,而 HAVING 查询条件中可以使用字段别名。

实例

mysql 表记录类似rowid mysql 操作数据记录_数据库_08

11、多表查询(交叉连接、内连接、外连接)

前面所讲的查询语句都是针对一个表的,但是在关系型数据库中,表与表之间是有联系的,所以在实际应用中,经常使用多表查询。多表查询就是同时查询两个或两个以上的表。

在 MySQL 中,多表查询主要有交叉连接、内连接和外连接。

11.1、笛卡尔积

笛卡尔积(Cartesian product)是指两个集合 X 和 Y 的乘积。

例如,有 A 和 B 两个集合,它们的值如下:

  • A = {1,2}
    B = {3,4,5}

集合 A×B 和 B×A 的结果集分别表示为:

  • A×B={(1,3), (1,4), (1,5), (2,3), (2,4), (2,5) };
    B×A={(3,1), (3,2), (4,1), (4,2), (5,1), (5,2) };

以上 A×B 和 B×A 的结果就叫做两个集合的笛卡尔积。得到的结果还是集合!

并且,从以上结果我们可以看出:

  • 两个集合相乘,不满足交换率,即 A×B≠B×A。
  • A 集合和 B 集合的笛卡尔积是 A 集合的元素个数 × B 集合的元素个数。

多表查询遵循的算法就是以上提到的笛卡尔积,表与表之间的连接可以看成是在做乘法运算。在实际应用中,应避免使用笛卡尔积,因为笛卡尔积中容易存在大量的不合理数据,简单来说就是容易导致查询结果重复、混乱。

11.2、 交叉连接

交叉连接(CROSS JOIN)一般用来返回连接表的笛卡尔积。交叉连接的语法格式如下:

SELECT <字段名> FROM <表1> CROSS JOIN <表2> [WHERE子句]

SELECT <字段名> FROM <表1>, <表2> [WHERE子句]

语法说明如下:

  • 字段名:需要查询的字段名称。
  • <表1><表2>:需要交叉连接的表名。
  • WHERE 子句:用来设置交叉连接的查询条件。

注意:多个表交叉连接时,在 FROM 后连续使用 CROSS JOIN 或,即可。以上两种语法的返回结果是相同的,但是第一种语法才是官方建议的标准写法。

当连接的表之间没有关系时,我们会省略掉 WHERE 子句,这时返回结果就是两个表的笛卡尔积,返回结果数量就是两个表的数据行相乘。需要注意的是,如果每个表有 1000 行,那么返回结果的数量就有 1000×1000 = 1000000 行,数据量是非常巨大的。所以,通过交叉连接的方式进行多表查询的这种方法并不常用,我们应该尽量避免这种查询。

直接上实例体会:

mysql 表记录类似rowid mysql 操作数据记录_sql_09

11.3、内连接

内连接(INNER JOIN)主要通过设置连接条件的方式,来移除查询结果中某些数据行的交叉连接。简单来说,就是利用条件表达式来消除交叉连接的某些数据行。

内连接使用 INNER JOIN 关键字连接两张表,并使用 ON 子句来设置连接条件。如果没有连接条件,INNER JOIN 和 CROSS JOIN 在语法上是等同的,两者可以互换。

内连接的语法格式如下:

SELECT <字段名> FROM <表1> INNER JOIN <表2> [ON子句]

语法说明如下。

  • 字段名:需要查询的字段名称。
  • <表1><表2>:需要内连接的表名。
  • INNER JOIN :内连接中可以省略 INNER 关键字,只用关键字 JOIN。
  • ON 子句:用来设置内连接的连接条件。
  • INNER JOIN 也可以使用 WHERE 子句指定连接条件,但是 INNER JOIN … ON 语法是官方的标准写法,而且 WHERE 子句在某些时候会影响查询的性能。

多个表内连接时,在 FROM 后连续使用 INNER JOIN 或 JOIN 即可。内连接可以查询两个或两个以上的表。

实例

mysql 表记录类似rowid mysql 操作数据记录_mysql_10

11.4 、外连接

内连接的查询结果都是符合连接条件的记录,而外连接会先将连接的表分为基表和参考表,再以基表为依据返回满足和不满足条件的记录。

外连接可以分为左外连接右外连接,下面根据实例分别介绍左外连接和右外连接。

左外连接(表一为基表、表二为参考表)
左外连接又称为左连接,使用 LEFT OUTER JOIN 关键字连接两个表,并使用 ON 子句来设置连接条件。

左连接的语法格式如下:

SELECT <字段名> FROM <表1> LEFT OUTER JOIN <表2> <ON子句>

语法说明如下。

  • 字段名:需要查询的字段名称。
  • <表1><表2>:需要左连接的表名。
  • LEFT OUTER JOIN:左连接中可以省略 OUTER 关键字,只使用关键字 LEFT JOIN。
    ON 子句:用来设置左连接的连接条件,不能省略。

上述语法中,“表1”为基表,“表2”为参考表。左连接查询时,可以查询出“表1”中的所有记录和“表2”中匹配连接条件的记录。如果“表1”的某行在“表2”中没有匹配行,那么在返回结果中,“表2”的字段值均为空值(NULL)
右外连接(表二为基表、表一为参考表)
右外连接又称为右连接,右连接是左连接的反向连接。使用 RIGHT OUTER JOIN 关键字连接两个表,并使用 ON 子句来设置连接条件。

右连接的语法格式如下:

SELECT <字段名> FROM <表1> RIGHT OUTER JOIN <表2> <ON子句>

语法说明如下。

  • 字段名:需要查询的字段名称。
  • <表1><表2>:需要右连接的表名。
  • RIGHT OUTER JOIN:右连接中可以省略 OUTER 关键字,只使用关键字 RIGHT JOIN。
    ON 子句:用来设置右连接的连接条件,不能省略。

与左连接相反,右连接以“表2”为基表,“表1”为参考表。右连接查询时,可以查询出“表2”中的所有记录和“表1”中匹配连接条件的记录。如果“表2”的某行在“表1”中没有匹配行,那么在返回结果中,“表1”的字段值均为空值(NULL)

例子演示

mysql 表记录类似rowid mysql 操作数据记录_数据库_11

12、MySQL子表查询(嵌套查询)

12.1、子表查询的使用

子查询是 MySQL 中比较常用的查询方法,通过子查询可以实现多表查询。子查询指将一个查询语句嵌套在另一个查询语句中。子查询可以在 SELECT、UPDATE 和 DELETE 语句中使用,而且可以进行多层嵌套。在实际开发时,子查询经常出现在 WHERE 子句中。

子查询在 WHERE 中的语法格式如下:

WHERE <表达式> <操作符> (子查询)

其中,操作符可以是比较运算符和 IN、NOT IN、EXISTS、NOT EXISTS 等关键字。

  • 1)IN | NOT IN
    表达式与子查询返回的结果集中的某个值相等时,返回 TRUE,否则返回 FALSE;若使用关键字 NOT,则返回值正好相反。
  • 2)EXISTS | NOT EXISTS
    用于判断子查询的结果集是否为空,若子查询的结果集不为空,返回 TRUE,否则返回 FALSE;若使用关键字 NOT,则返回的值正好相反。

实例:

mysql 表记录类似rowid mysql 操作数据记录_sql_12

12.2、子查询语句的位置(注意事项)

在完成较复杂的数据查询时,经常会使用到子查询,编写子查询语句时,要注意如下事项。

  1. 子查询语句可以嵌套在 SQL 语句中任何表达式出现的位置
    在 SELECT 语句中,子查询可以被嵌套在 SELECT 语句的列、表和查询条件中,即 SELECT 子句,FROM 子句、WHERE 子句、GROUP BY 子句和 HAVING 子句。

WHERE 子句中嵌套子查询的使用方法

mysql 表记录类似rowid mysql 操作数据记录_oracle_13


下面是子查询在 SELECT 子句和 FROM 子句中的使用语法。

嵌套在 SELECT 语句的 SELECT 子句中的子查询语法格式如下。

SELECT (子查询) FROM 表名;//暂时不知道怎么写这个语句,有人说不能这样嵌套的。大家发现告诉我一声

提示:子查询结果为单行单列,但不必指定列别名。

嵌套在 SELECT 语句的 FROM 子句中的子查询语法格式如下。

SELECT * FROM (子查询) AS 表的别名;

注意:必须为表指定别名。一般返回多行多列数据记录,可以当作一张临时表。
2) 只出现在子查询中而没有出现在父查询中的表不能包含在输出列中
多层嵌套子查询的最终数据集只包含父查询(即最外层的查询)的 SELECT 子句中出现的字段,而子查询的输出结果通常会作为其外层子查询数据源或用于数据判断匹配。

常见错误如下:

SELECT * FROM (SELECT * FROM result);

这个子查询语句产生语法错误的原因在于主查询语句的 FROM 子句是一个子查询语句,因此应该为子查询结果集指定别名。正确代码如下。

SELECT * FROM (SELECT * FROM result) AS Temp;

mysql 表记录类似rowid mysql 操作数据记录_mysql_14

13、REGEXP:正则表达式匹配(同java…)

MySQL 中,使用 REGEXP 关键字指定正则表达式的字符匹配模式,其基本语法格式如下:

属性名 REGEXP '匹配方式'

mysql 表记录类似rowid mysql 操作数据记录_mysql 表记录类似rowid_15


实例:

mysql 表记录类似rowid mysql 操作数据记录_mysql_16

14、INSERT:插入数据

数据库与表创建成功以后,需要向数据库的表中插入数据。在 MySQL 中可以使用 INSERT 语句向数据库已有的表中插入一行或者多行元组数据。
基本语法
INSERT 语句有两种语法形式,分别是 INSERT…VALUES 语句和 INSERT…SET 语句。

  1. INSERT…VALUES语句
    INSERT VALUES 的语法格式为:
INSERT INTO <表名> [ <列名1> [ , … <列名n>] ]
VALUES (值1) [… , (值n) ];

语法说明如下。

  • <表名>:指定被操作的表名。
  • <列名>:指定需要插入数据的列名。若向表中的所有列插入数据,则全部的列名均可以省略,直接采用 INSERT<表名>VALUES(…) 即可。
  • VALUES 或 VALUE 子句:该子句包含要插入的数据清单。数据清单中数据的顺序要和列的顺序相对应。
  1. INSERT…SET语句
    语法格式为:
INSERT INTO <表名>
SET <列名1> = <值1>,
        <列名2> = <值2>,
        …

此语句用于直接给表中的某些列指定对应的列值,即要插入的数据的列名在 SET 子句中指定,col_name 为指定的列名,等号后面为指定的数据,而对于未指定的列,列值会指定为该列的默认值。

由 INSERT 语句的两种形式可以看出:

  • 使用 INSERT…VALUES 语句可以向表中插入一行数据,也可以插入多行数据;
  • 使用 INSERT…SET 语句可以指定插入行中每列的值,也可以指定部分列的值;
  • INSERT…SELECT 语句向表中插入其他表的数据。
  • 采用 INSERT…SET 语句可以向表中插入部分列的值,这种方式更为灵活;
  • INSERT…VALUES 语句可以一次插入多条数据。

在 MySQL 中,用单条 INSERT 语句处理多个插入要比使用多条 INSERT 语句更快。

当使用单条 INSERT 语句插入多行数据的时候,只需要将每行数据用圆括号括起来即可。

实例

mysql 表记录类似rowid mysql 操作数据记录_oracle_17


mysql 表记录类似rowid mysql 操作数据记录_mysql_18

15、UPDATE:修改数据

在 MySQL 中,可以使用 UPDATE 语句来修改、更新一个或多个表的数据。
UPDATE 语句的基本语法
使用 UPDATE 语句修改单个表,语法格式为:

UPDATE <表名> SET 字段 1=值 1 [,字段 2=值 2… ] [WHERE 子句 ]
[ORDER BY 子句] [LIMIT 子句]

语法说明如下:

  • <表名>:用于指定要更新的表名称。
  • SET 子句:用于指定表中要修改的列名及其列值。其中,每个指定的列值可以是表达式,也可以是该列对应的默认值。如果指定的是默认值,可用关键字 DEFAULT 表示列值。
  • WHERE 子句:可选项。用于限定表中要修改的行。若不指定,则修改表中所有的行。
  • ORDER BY 子句:可选项。用于限定表中的行被修改的次序。
  • LIMIT 子句:可选项。用于限定被修改的行数。
    注意:修改一行数据的多个列值时,SET 子句的每个值用逗号分开即可。

16、DELETE:删除数据

在 MySQL 中,可以使用 DELETE 语句来删除表的一行或者多行数据。
删除单个表中的数据
使用 DELETE 语句从单个表中删除数据,语法格式为:

DELETE FROM <表名> [WHERE 子句] [ORDER BY 子句] [LIMIT 子句]

语法说明如下:

  • <表名>:指定要删除数据的表名。
  • ORDER BY 子句:可选项。表示删除时,表中各行将按照子句中指定的顺序进行删除。
  • WHERE 子句:可选项。表示为删除操作限定删除条件,若省略该子句,则代表删除该表中的所有行。
  • LIMIT 子句:可选项。用于告知服务器在控制命令被返回到客户端前被删除行的最大值。

注意:在不使用 WHERE 条件的时候,将删除所有数据。

实例:

mysql 表记录类似rowid mysql 操作数据记录_mysql_19

17、TRUNCATE:清空表记录

17.1、语法

MySQL 提供了 DELETE 和 TRUNCATE 关键字来删除表中的数据。本节主要讲解 TRUNCATE 关键字的使用。

TRUNCATE 关键字用于完全清空一个表。其语法格式如下:

TRUNCATE [TABLE] 表名

其中,TABLE 关键字可省略。

mysql 表记录类似rowid mysql 操作数据记录_数据库_20

17.2、TRUNCATE 和 DELETE 的区别

从逻辑上说,TRUNCATE 语句与 DELETE 语句作用相同,但是在某些情况下,两者在使用上有所区别。

  • DELETE 是 DML 类型的语句;TRUNCATE 是 DDL 类型的语句。它们都用来清空表中的数据。
  • DELETE 是逐行一条一条删除记录的;TRUNCATE 则是直接删除原来的表,再重新创建一个一模一样的新表,而不是逐行删除表中的数据,执行数据比 DELETE 快。因此需要删除表中全部的数据行时,尽量使用 TRUNCATE 语句, 可以缩短执行时间。
  • DELETE 删除数据后,配合事件回滚可以找回数据;TRUNCATE 不支持事务的回滚,数据删除后无法找回。
  • DELETE 删除数据后,系统不会重新设置自增字段的计数器;TRUNCATE 清空表记录后,系统会重新设置自增字段的计数器。
  • DELETE 的使用范围更广,因为它可以通过 WHERE 子句指定条件来删除部分数据;而 TRUNCATE 不支持 WHERE 子句,只能删除整体。
  • DELETE 会返回删除数据的行数,但是 TRUNCATE 只会返回 0,没有任何意义。

总结
当不需要该表时,用 DROP;当仍要保留该表,但要删除所有记录时,用 TRUNCATE;当要删除部分记录时,用 DELETE。

18、MySQL如何处理无效数据值?

你传给 MySQL 什么样的数据,它就会存储什么样的数据。如果在存储数据时没有对它们进行验证,那么在把它们检索出来时得到的就不一定是你所期望的内容。

下面介绍 MySQL 默认情况下如何处理非正常数据和启用各种 SQL 模式时会对数据处理产生哪些影响。

默认情况下MySQL 会按照以下规则来处理越界(即超出取值范围)的值和其他非正常值:

  • 对于数值列或 TIME 列,超出合法取值范围的那些值将被截断到取值范围最近的那个端点,并把结果值存储起来。
  • 对于除 TIME 列以外的其他类型列,非法值会被转换成与该类型一致的“零”值。
  • 对于字符串列(不包括 ENUM 或 SET),过长的字符串将被截断到该列的最大长度。
  • 给 ENUM 或 SET 类型列进行赋值时,需要根据列定义里给出的合法取值列表进行。如果把不是枚举成员的值赋给 ENUM 列,那么列的值就会变成空字符串。如果把包含非集合成员的子字符串的值赋给 SET 列,那么这些字符串会被清理,剩余的成员才会被赋值给列。

如果在执行增删改查等语句时发生了上述转换,那么 MySQL 会给出警告消息。在执行完其中的某一条语句之后,可以使用 SHOW WARNINGS 语句来查看警告消息的内容。

如果需要在插入或更新数据时执行更严格的检查,那么可以启用以下两种 SQL 模式中的一种:

SET sql_mode = 'STRICT_ALL_TABLES' ;
SET sql_mode = 'STRICT_TRANS_TABLES';

对于支持事务的表,这两种模式都是一样的。如果发现某个值无效或缺失,那么会产生一个错误,并且语句会中止执行,并进行回滚,就像什么事都没发生过一样。

对于不支持事务的表,这两种模式有以下效果。

  1. 对于这两种模式,如果在插入或修改第一个行时,发现某个值无效或缺失,那么结果会产生一个错误,语句会中止执行,就像什么事都未发生过一样。 这跟事务表的行为很相似。
  2. 在用于插入或修改多个行的语句里,如果在第一行之后的某个行出现了错误,那么会出现某些行被修改的情况。这两种模式决定着,这条语句此时此刻是要停止执行,还是要继续执行。
    在 STRICT_ALL_TABLES 模式下,会抛出一个错误,并且语句会停止执行。因为受该语句影响的许多行都已被修改,所以这将会导致“部分更新”问题。
    在 STRICT_TRANS_TABLES 模式下,对于非事务表,MySQL 会中止语句的执行。只有这样做,才能达到事务表那样的效果。只有当第一行发生错误时,才能达到这样的效果。如果错误在后面的某个行上,那么就会出现某些行被修改的情况。由于对于非事务表,那些修改是无法撤销的,因此 MySQL 会继续执行该语句,以避免出现“部分更新”的问题。它会把所有的无效值转换为与其最接近的合法值。对于缺失的值,MySQL 会把该列设置成其数据类型的隐式默认值,

通过以下模式可以对输入的数据进行更加严格的检查:

  • ERROR_ FOR_ DIVISION_ BY_ ZERO:在严格模式下,如果遇到以零为除数的情况,它会阻止数值进入数据库。如果不在严格模式下,则会产生一条警告消息,并插入 NULL。
  • NO_ ZERO_ DATE:在严格模式下,它会阻止“零”日期值进入数据库。
  • NO_ ZERO_ IN_ DATE:在严格模式下,它会阻止月或日部分为零的不完整日期值进入数据库。

简单来说,MySQL 的严格模式就是 MySQL 自身对数据进行的严格校验,例如格式、长度、类型等。比如一个整型字段我们写入一个字符串类型的数据,在非严格模式下 MySQL 不会报错。如果定义了 char 或 varchar 类型的字段,当写入或更新的数据超过了定义的长度也不会报错。

虽然我们会在代码中做数据校验,但一般认为非严格模式对于编程来说没有任何好处。MySQL开启严格模式从一定程序上来讲也是对我们代码的一种测试,如果我们没有开启严格模式并且在开发过程中也没有遇到错误,那么在上线或代码移植的时候将有可能出现不兼容的情况,因此在开发过程做最好开启 MySQL 的严格模式

可通过select @@sql_mode;命令查看当前是严格模式还是非严格模式。

mysql 表记录类似rowid mysql 操作数据记录_oracle_21

例如,如果想让所有的存储引擎启用严格模式,并对“被零除”错误进行检查,那么可以像下面这样设置 SQL 模式:

SET sql_mode='STRICT_ALL_TABLES, ERROR_FOR_DIVISION_BY_ZERO' ;

mysql 表记录类似rowid mysql 操作数据记录_数据库_22

如果想启用严格模式,以及所有的附加限制,那么最为简单的办法是启用 TRADITIONAL 模式:

SET sql_ mode='TRADITIONAL' ;

TRADITIONAL 模式的含义是“启用严格模式,当向 MySQL 数据库插入数据时,进行数据的严格校验,保证错误数据不能插入。用于事务表时,会进行事务的回滚”。

可以选择性地在某些方面弱化严格模式。如果启用了 SQL 的 ALLOW_ INVALID_ DATES 模式,那么MySQL将不会对日期部分做全面检查。相反,它只会要求月份值在 1~12 之间,而天数处于 1~31 之间,即允许像‘2000-02-30’或‘2000-06-31’这样的无效值。

另一个制止错误的办法是在 INSERT 或 UPDATE 语句里使用 IGNORE 关键字。这样那些会因无效值而导致错误的语句,将只会导致警告的出现。这些选项能让你灵活地为你的应用选择正确的有效性检查级别。