MySQL数据库 第5章:单表操作

5.1 数据操作

5.1.1 复制表结构和数据

1. 复制表结构
先思考一个问题,如何快速的创建与已有表结构相同的数据表?

根据前面章节的学习,有两种方式:

但是,MySQL提供了一种更快捷的方式:复制表结构

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] 表名
{ LIKE 旧表名| (LIKE旧表名 ) };

作用是:从“旧表名”中复制一份相同的表结构,但不会复制表中保存的数据。
其中,“{}”表示语法在使用时可以任选其中一种,“|”表示或的意思。[]表示可选项

举例如下:

CREATE TABLE mydb.my_goods LIKE sh_goods;

作用:复制表shgoods的表结构 到 mydb.mygoods表中

2. 复制数据

上面讲了复制表结构,那如何将表中的已有数据快速的添加到指定表中?

根据前面章节的学习,只有一种方式:

MySQL提供了一种快捷的方式:复制表数据

INSERT [INTO] 数据表名1 [(字段列表)] SELECT [(字段列表)] FROM 数据表名2;

数据表名1和数据表名2通常使用的是同一个表(如my_goods表)
可在短期内快速增加表的数据量,测试表的压力以及效率等。

举例:
从shgoods表中复制数据到mygoods表中:

INSERT INTO mydb.my_goods SELECT * FROM sh_goods;

结果可以正常执行,但如果我们再执行一遍就会出错:

mysql> INSERT INTO mydb.my_goods SELECT * FROM sh_goods;
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

提示我们主键有个重复条目‘1’,这就是主键冲突,以上主键冲突的问题,数据复制时可以指定除id主键外的任意字段完成。

mysql> INSERT INTO mydb.my_goods (category_id, name, keyword, price,
-> content) SELECT category_id, name, keyword, price, content
-> FROM sh_goods;
Query OK, 10 rows affected (0.00 sec)
Records: 10 Duplicates: 0 Warnings: 0

5.1.1 节的测试代码如下,大家复制后一条条执行,看看效果:

-- create table goods(id int unsigned primary key auto_increment,name varchar(36))
-- create table new_goods like goods
-- insert into goods values(0,'book')
-- insert into mysql.new_goods select * from goods
-- insert into mysql.new_goods(name) select name from goods

扩展知识点:临时表
临时表就是当前会话中有效,重新连接数据库服务器后该表就不存在了。

临时表:是一种仅在当前会话中可见,并在当前会话关闭时自动删除的数据表。
作用:主要用于临时存储数据。
语法:只需在CREATE与TABLE关键中间添加TEMPORARY即可。

# 方式1:创建临时表
CREATE TEMPORARY TABLE mydb.tmp_table1 (id int);
# 方式2:创建临时表
CREATE TEMPORARY TABLE mydb.tmp_table2 SELECT id,name FROM shop.sh_goods;

建临时表时指定的数据库可以是MySQL服务器中存在的数据库也可以是不存在的数据库。
若数据库不存在,操作临时表时必须使用“数据库.临时表名”指定临时表所在的数据库。

临时表中数据的操作与普通表相同,都可以进行SELECT、INSERT、UPDATE和DELETE操作。
SHOW TABLES不能查看指定数据库下有哪些临时表.
临时表的表名必须使用ALTER TABLE修改,而不能使用RENAME TABLE…TO修改。

5.1.2 解决主键冲突

mysql> INSERT INTO mydb.my_goods(id, name, content, keyword)
-> VALUES (20, '橡皮', '修正书写错误', '文具');
ERROR 1062 (23000): Duplicate entry '20' for key 'PRIMARY'

解决主键冲突:

  1. 方式一:主键冲突更新
    当插入数据的过程中若发生主键冲突,则插入数据操作利用更新的方式实现。

INSERT [INTO] 数据表名 [(字段列表)] {VALUES | VALUE} (字段列表)
ON DUPLICATE KEY UPDATE 字段名1 = 新值1[,字段名2 = 新值2] …;

举例:

mysql> INSERT INTO mydb.my_goods (id, name, content, keyword)
-> VALUES (20, '橡皮', '修正书写错误', '文具')
-> ON DUPLICATE KEY UPDATE name = '橡皮', content = '修正书写错误',
-> keyword = '文具';
Query OK, 2 rows affected (0.00 sec)
mysql> SELECT name, content, keyword FROM mydb.my_goods WHERE id = 20;
+------+------------+---------+
| name | content | keyword |
+------+------------+---------+
| | | |
+------+------------+---------+
1 row in set (0.00 sec)

  1. 方式二:主键冲突替换
    当插入数据的过程中若发生主键冲突,则删除此条记录,并重新插入。

REPLACE [INTO] 数据表名 [(字段列表)]
{VALUES | VALUE} (值列表) [, (值列表)] …;

举例:

mysql> REPLACE INTO mydb.my_goods (id, name, content, keyword)
-> VALUES (20, '橡皮', '修正书写错误', '文具');
Query OK, 2 rows affected (0.00 sec)
mysql> SELECT name, content, keyword FROM mydb.my_goods WHERE id = 20;
+------+------------+---------+
| name | content | keyword |
+------+------------+---------+
| | | |
+------+------------+---------+
1 row in set (0.00 sec)

REPLACE语句与INSERT语句的使用类似,区别在于前者每执行一次就会发生两个操作(删除记录和插入记录)。

5.1.3 清空数据

TRUNCATE [TABLE] 表名

例如:

mysql> TRUNCATE TABLE mydb.my_goods;
Query OK, 0 rows affected (0.08 sec)

TRUNCATE操作与DELETE语句在本质上的区别:

  1. 实现方式不同:TRUNCATE本质上先执行删除(DROP)数据表的操作,然后再根据有效的表结构文件(.frm)重新创建数据表的方式来实现数据清空操作。而DELETE语句则是逐条的删除数据表中保存的记录。
  2. 执行效率不同:在针对大型数据表(如千万级的数据记录)时,TRUNCATE清空数据的实现方式,决定了它比DELETE语句删除数据的方式执行效率更高。
  3. 对AUTO_INCREMENT的字段影响不同:TRUNCATE清空数据后,再次向表中添加数据,自动增长字段会从默认的初始值重新开始,而使用DELETE语句删除表中的记录时,则不影响自动增长值。
  4. 删除数据的范围不同:TRUNCATE语句只能用于清空表中的所有记录,而DELETE语句可通过WHERE指定删除满足条件的部分记录。
  5. 返回值含义不同:TRUNCATE操作的返回值一般是无意义的,而DELETE语句则会返回符合条件被删除的记录数。
  6. 所属SQL语言的不同组成部分:DELETE语句属于DML数据操作语句,而TRUNCATE通常被认为是DDL数据定义语句。

案例:
为my_goods插入10条记录后,使用TRUNCATE清空并重新插入数据。

mysql> TRUNCATE TABLE mydb.my_goods;
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO mydb.my_goods (name, content, keyword)
-> VALUES ('苹果', '一种很有营养的水果', '水果');
Query OK, 1 row affected (0.00 sec)
mysql> SELECT id, name, content, keyword FROM mydb.my_goods;
+----+------+--------------------+------------+
| id | name | content | keyword |
+----+------+--------------------+------------+
| 1 | | | |
+----+------+--------------------+------------+
1 row in set (0.00 sec)

为my_goods插入10条记录后,使用DELETE删除并重新插入数据。

mysql> DELETE FROM mydb.my_goods;
Query OK, 10 rows affected (0.00 sec)
mysql> INSERT INTO mydb.my_goods (name, content, keyword)
-> VALUES ('苹果', '一种很有营养的水果', '水果');
Query OK, 1 row affected (0.00 sec)
mysql> SELECT id, name, content, keyword FROM mydb.my_goods;
+----+------+--------------------+------------+
| id | name | content | keyword |
+----+------+--------------------+------------+
| 11 | | | |
+----+------+--------------------+------------+
1 row in set (0.00 sec)

注意看主键的值不同,truncate后主键的值为1,delete主键的值为11
对比TRUNCATE操作与DELETE语句操作的区别:

5.1.4 去除重复记录

实际应用中,出于对数据的分析需求,有时需要去除查询记录中重复的数据。
例如,查看商品表中共有几种分类,此时可以使用SELECT语句的选项。

SELECT select选项 字段列表 FROM 数据表;

未去除重复记录演示:


去除重复记录演示:

5.2 排序与限量

5.2.1 排序

在项目开发时,为了使查询的数据结果满足用户的要求,通常会对查询出的数据进行上升或下降的排序。
MySQL提供了两种排序的方式,分别为单字段排序和多字段排序。

单字段排序:指的是查询时仅按照一个指定字段进行升序或降序排序。

SELECT *|{字段列表} FROM 数据表名
ORDER BY 字段名 [ASC | DESC];

SELECT *|{字段列表} FROM 数据表名
ORDER BY 字段名1 [ASC | DESC] [, 字段名2 [ASC | DESC]]…;

多字段排序首先按照字段名1进行排序,当字段1的值相同时,再按照字段2进行排序,依次类推。

5.2.2 限量

对于一次性查询出的大量记录,不仅不便于阅读查看,还会浪费系统效率。
MySQL中提供了一个关键字LIMIT,可以限定记录的数量,也可以指定查询从哪一条记录开始(通常用于分页)。

SELECT [select 选项] 字段列表 FROM 数据表名
[WHERE 条件表达式] [ORDER BY 字段 ASC|DESC]
LIMIT [OFFSET,] 记录数;

举例:
限制记录数:查询shgoods表中价格最贵的商品
![在这里插入图片描述](https://img-blog.csdnimg.cn/7110a97dad74486d8154e342cc14f4e9.png?x-oss-process=image/watermark,typed3F5LXplbmhlaQ,shadow50,textQ1NETiBA5biD6KGj5Lmm55SfLVB5dGhvbg,size13,colorFFFFFF,t70,gse,x16)获取指定区间的记录数:从第1条记录开始的5条商品记录:![在这里插入图片描述](https://img-blog.csdnimg.cn/98b350a411a147d1a1f44c5cd73dd056.png?x-oss-process=image/watermark,typed3F5LXplbmhlaQ,shadow50,textQ1NETiBA5biD6KGj5Lmm55SfLVB5dGhvbg,size16,colorFFFFFF,t70,gse,x_16)

排序后限量更新或删除数据
在MySQL中除了对查询记录进行排序和限量外,对数据表中记录的更新与删除操作也可以进行排序和限量。

# 数据更新的排序与限量
UPDATE 数据表名 SET 字段=新值, … [WHERE 条件表达式]
ORDER BY 字段 ASC|DESC LIMIT 记录数;
# 数据删除的排序与限量
DELETE FROM 数据表名 [WHERE 条件表达式]
ORDER BY 字段 ASC|DESC LIMIT 记录数;

例如:
把shgoods表中最便宜的两个商品的stock(库存)设置为500:
![在这里插入图片描述](https://img-blog.csdnimg.cn/aaea2f76d048413ab3efbf899b5d4b8a.png?x-oss-process=image/watermark,typed3F5LXplbmhlaQ,shadow50,textQ1NETiBA5biD6KGj5Lmm55SfLVB5dGhvbg==,size20,colorFFFFFF,t70,gse,x_16)

5.3 分组与聚合函数

5.3.1 分组

分组统计:查询时在WHERE条件后添加GROUP BY即可进行分组统计。

SELECT [select 选项] 字段列表 FROM 数据表名
[WHERE 条件表达式] GROUP BY 字段名;

例如:
通过聚合函数MAX()获取每个分类下商品的最高价格。

mysql> SELECT category_id, MAX(price) FROM sh_goods GROUP BY category_id;
+-------------+------------+
| category_id | MAX(price) |
+-------------+------------+
| 3 | 15.00 |
| 6 | 1999.00 |
| 8 | 69.00 |
| 9 | 109.00 |
| 10 | 2000.00 |
| 12 | 5999.00 |
| 15 | 299.00 |
| 16 | 48.00 |
+-------------+------------+
8 rows in set (0.00 sec)

分组排序:默认分组操作的字段提供按升序排序,因此在分组时可为指定的字段进行升序或降序排序。

SELECT [select 选项] 字段列表 FROM 数据表名
[WHERE 条件表达式] GROUP BY 字段名 [ASC | DESC];

GROUP BY分组排序的实现不需要使用ORDER BY,直接在分组字段后添加ASC(升序,默认值可省略)或DESC(降序)即可。

例如:根据shgoods表中的分类id进行分组降序操作
![在这里插入图片描述](https://img-blog.csdnimg.cn/bb13f622710749ac91821f1164c6a7cf.png?x-oss-process=image/watermark,typed3F5LXplbmhlaQ,shadow50,textQ1NETiBA5biD6KGj5Lmm55SfLVB5dGhvbg==,size19,colorFFFFFF,t70,gse,x16)
GROUPCONCAT(id)的作用是将指定字段id的值连成一个字符串,比如最后一个categoryid=3时,id有3个,分别为1,2,3,所以,GROUPCONCAT(id)=1,2,3

多分组统计:按某个字段进行分组后,对已经分组的数据进行再次分组的操作。

SELECT [select 选项] 字段列表 FROM 数据表名
[WHERE 条件表达式]
GROUP BY 字段名1 [ASC | DESC], [, 字段名2 [ASC | DESC]]…;

查询出的数据首先按照字段1进行分组排序,再将字段1相同的结果按照字段2进行分组排序,依次类推。

例如:以评分score降序分组后,再以评论数commentcount升序排序
![在这里插入图片描述](https://img-blog.csdnimg.cn/9ae664db9b494aed9ddae3d8b3a516f9.png?x-oss-process=image/watermark,typed3F5LXplbmhlaQ,shadow50,textQ1NETiBA5biD6KGj5Lmm55SfLVB5dGhvbg==,size19,colorFFFFFF,t70,gse,x_16)
回溯统计:在根据指定字段分组后,系统又自动对分组的字段向上进行了一次新的统计并产生一个新的统计数据,且该数据对应的分组字段值为NULL。

SELECT [select 选项] 字段列表 FROM 数据表名
[WHERE 条件表达式]
GROUP BY 字段名1 [ASC | DESC], [, 字段名2 [ASC | DESC]]… WITH ROLLUP;

单字段分组的回溯统计

mysql> SELECT category_id, COUNT(*)
-> FROM sh_goods GROUP BY category_id WITH ROLLUP;
+-------------+----------+
| category_id | COUNT(*) |
+-------------+----------+
| 3 | 3 |
| 6 | 1 |
| 8 | 1 |
| 9 | 1 |
| 10 | 1 |
| 12 | 1 |
| 15 | 1 |
| 16 | 1 |
| NULL | 10 |
+-------------+----------+
9 rows in set (0.00 sec)

多字段分组的回溯统计

mysql> SELECT score, comment_count, COUNT(*)
-> FROM sh_goods
-> GROUP BY score, comment_count WITH ROLLUP;
+-------+---------------+----------+
| score | comment_count | COUNT(*) |
+-------+---------------+----------+
| 2.50 | 200 | 1 |
| 2.50 | NULL | 1 |
| 3.90 | 500 | 2 |
| 3.90 | NULL | 2 |
| 4.50 | 1000 | 1 |
| 4.50 | NULL | 1 |
| 4.80 | 6000 | 1 |
| 4.80 | 98000 | 1 |
| 4.80 | NULL | 2 |
| 4.90 | 40000 | 2 |
| 4.90 | NULL | 2 |
| 5.00 | 98000 | 2 |
| 5.00 | NULL | 2 |
| NULL | NULL | 10 |
+-------+---------------+----------+
14 rows in set (0.00 sec)

虽然回溯统计对数据的分析很有帮助,但是MySQL的同一个查询语句中回溯统计(WITH ROLLUP)与排序(ORDER BY)仅能出现一个。

统计筛选:对查询的数据分组时,可以利用HAVING根据条件进行数据筛选,它与前面学习过的WHERE功能相同,但是在实际运用时两者有一定的区别。

SELECT [select 选项] 字段列表 FROM 数据表名
[WHERE 条件表达式]
GROUP BY 字段名 [ASC | DESC], …[WITH ROLLUP]
HAVING 条件表达式;

获取评分和评分数不同的情况下,含有两件商品的对应商品id:

mysql> SELECT score, comment_count, GROUP_CONCAT(id)
-> FROM sh_goods
-> GROUP BY score, comment_count
-> HAVING COUNT(*) = 2;
+-------+---------------+------------------+
| score | comment_count | GROUP_CONCAT(id) |
+-------+---------------+------------------+
| 3.90 | 500 | 2,7 |
| 4.90 | 40000 | 1,9 |
| 5.00 | 98000 | 3,5 |
+-------+---------------+------------------+
3 rows in set (0.00 sec)

在查询中使用别名:
在MySQL中执行查询操作时,可以根据具体情况为获取的字段设置别名。
例如,通过设置别名来缩短字段的名称长度。

# 字段设置别名
SELECT 字段1 [AS] 别名1, 字段2 [AS] 别名2 [, …] FROM 表名
# 表设置别名
SELECT 表别名.字段 [, …] FROM 表名 [AS] 表别名

为字段设置别名,举例:

mysql> SELECT category_id cid, MAX(price) max_price FROM sh_goods
-> GROUP BY cid HAVING cid = 3 OR cid = 6;
+-----+-----------+
| cid | max_price |
+-----+-----------+
| 3 | 15.00 |
| 6 | 1999.00 |
+-----+-----------+
1 row in set (0.00 sec)

为表设置别名

SELECT g.category_id cid, MAX(g.price) max_price FROM sh_goods g
GROUP BY cid HAVING cid = 3 OR cid = 6;

5.3.2 聚合函数

通过前面的学习可知,在对数据进行分组统计时,经常需要结合MySQL提供的聚合函数才能够统计出具有价值的数据。

例如,获取每种商品分类下的商品数量、最高价格的商品、最低价格的商品等。
为此,MySQL中的聚合函数就可在查询数据时提供一些特殊的功能。

单独使用聚合函数统计数据

mysql> SELECT MAX(price), MIN(price) FROM sh_goods;
+------------+------------+
| MIN(price) | MAX(price) |
+------------+------------+
| 5999.00 | 0.50 |
+------------+------------+
1 row in set (0.00 sec)

聚合函数与分组结合使用统计数据

mysql> SELECT category_id, MAX(price), MIN(price)
-> FROM sh_goods GROUP BY category_id HAVING COUNT(*) > 2;
+-------------+------------+------------+
| category_id | MAX(price) | MIN(price) |
+-------------+------------+------------+
| 3 | 15.00 | 0.50 |
+-------------+------------+------------+
1 row in set (0.00 sec)

MySQL5.7.22中新增函数JSONARRAYAGG()和JSONOBJECTAGG()

5.4 运算符

5.4.1 算术运算符

算术运算符适用于数值类型的数据,通常应用在SELECT查询结果的字段中使用,在WHERE条件表达式中应用较少。

注意事项:

  1. 运算符+、-和*的操作数都是无符号整型,则运算结果也是无符号整型。

mysql> SELECT id, id+1, id-1, id*2 FROM sh_goods LIMIT 5;
+----+------+------+------+
| id | id+1 | id-1 | id*2 |
+----+------+------+------+
| 1 | 2 | 0 | 2 |
| 2 | 3 | 1 | 4 |
| 3 | 4 | 2 | 6 |
| 4 | 5 | 3 | 8 |
| 5 | 6 | 4 | 10 |
+----+------+------+------+
5 rows in set (0.00 sec)

提出问题:默认运算符-的操作数若都为无符号整型,则结果一定是无符号的整型,若操作数的差值为负数,那么系统就会报错。
解决办法:使用CAST(... AS SIGNED)将无符号数据强制转换为有符号的数据。

默认无符号整型的减法运算

mysql> SELECT id-3 FROM sh_goods LIMIT 5;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(`shop`.`sh_goods`.`id` - 3)'

有负数所以报错了,解决办法:
有符号的减法运算结果:

mysql> SELECT CAST(id AS SIGNED)-3 FROM sh_goods LIMIT 5;
+----------------------+
| CAST(id AS sIGNED)-3 |
+----------------------+
| -2 |
| -1 |
| 0 |
| 1 |
| 2 |
+----------------------+
5 rows in set (0.00 sec)

  1. 浮点数运算精度

mysql> SELECT name, price, stock, price*0.75, stock+850.00
-> FROM sh_goods WHERE score = 5;
+----------+---------+-------+------------+--------------+
| name | price | stock | price*0.75 | stock+850.00 |
+----------+---------+-------+------------+--------------+
| | 1.00 | 500 | 0.7500 | 1350.00 |
| | 1999.00 | 0 | 1499.2500 | 850.00 |
+----------+---------+-------+------------+--------------+
2 rows in set (0.00 sec)

运算符 / 在MySQL中用于除法操作,且运算结果使用浮点数表示。
浮点数的精度等于被除数的精度加上系统变量pprecisionincrement设置的除法精度增长值(默认值为4)。

mysql> SHOW VARIABLES LIKE 'p_precision_increment';
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| p_precision_increment | 4 |
+-------------------------+-------+
1 row in set, 1 warning (0.00 sec)


除法运算中除数如果为0,则系统显示的执行结果为NULL。

在算术运算中,NULL是一个特殊的值,它参与的算术运算结果均为NULL。

mysql> SELECT NULL+1, 3-NULL, 7*NULL, 2/NULL, NULL/3;
+--------+--------+--------+--------+--------+
| NULL+1 | 3-NULL | 7*NULL | 2/NULL | NULL/3 |
+--------+--------+--------+--------+--------+
| NULL | NULL | NULL | NULL | NULL |
+--------+--------+--------+--------+--------+
1 row in set (0.00 sec)

在MySQL中,运算符DIV与 / 都能实现除法运算,区别在于前者的除法运算结果会去掉小数部分,只返回整数部分。

mysql> SELECT 8/5, 8 DIV 5, 0.6/1.2, 0.6 DIV 1.2;
+--------+---------+---------+-------------+
| 8/5 | 8 DIV 5 | 0.6/1.2 | 0.6 DIV 1.2 |
+--------+---------+---------+-------------+
| 1.6000 | 1 | 0.50000 | 0 |
+--------+---------+---------+-------------+
1 row in set (0.00 sec)

MySQL中的运算符MOD与%功能相同,都用于取模运算。

mysql> SELECT 8 MOD 5, -8 MOD 5, 8 MOD -5, -8 MOD -5;
+---------+----------+----------+-----------+
| 8 MOD 5 | -8 MOD 5 | 8 MOD -5 | -8 MOD -5 |
+---------+----------+----------+-----------+
| 3 | -3 | 3 | -3 |
+---------+----------+----------+-----------+
1 row in set (0.00 sec)

关于算术运算,除了算术运算符外,MySQL还提供了很多进行数学运算的函数。



RAND()函数用于返回0到1之间的随机数。
若要获取指定区间(min≤num<max)内的随机数时,使用表达式FLOOR(min+ RAND() * (max − min))获取。

例如:获取大于等于1且小于10的任意一个随机整数

mysql> SELECT FLOOR(1+RAND()*(10-1));
+------------------------+
| FLOOR(1+RAND()*(10-1)) |
+------------------------+
| 7 |
+------------------------+
1 row in set (0.00 sec)

若要获取相同的随机数,可为RAND()函数添加整数参数:

mysql> SELECT RAND(4);
+---------------------+
| RAND(4) |
+---------------------+
| 0.15595286540310166 |
+---------------------+
1 row in set (0.00 sec)
mysql> SELECT RAND();
+--------------------+
| RAND() |
+--------------------+
| 0.9753922950247231 |
+--------------------+
1 row in set (0.00 sec)
mysql> SELECT RAND(4);
+---------------------+
| RAND(4) |
+---------------------+
| 0.15595286540310166 |
+---------------------+
1 row in set (0.00 sec

随机获取某一商品分类下的所有商品id

mysql> SELECT category_id, GROUP_CONCAT(id) FROM sh_goods
-> GROUP BY category_id ORDER BY RAND() LIMIT 1;
+-------------+------------------+
| category_id | GROUP_CONCAT(id) |
+-------------+------------------+
| 3 | 1,2,3 |
+-------------+------------------+
1 row in set (0.00 sec)

5.4.2 比较运算符

比较运算符是MySQL常用运算符之一,通常应用在条件表达式中对结果进行限定。
MySQL中比较运算符的结果值有3种:

mysql> SELECT 5>='5', 3.0<>3;
+--------+--------+
| 5>='5' | 3.0<>3 |
+--------+--------+
| 1 | 0 |
+--------+--------+
1 row in set (0.00 sec)

比较运算符=、>、<、>=、<=、<>、!=在与NULL进行比较时,结果均为NULL。

mysql> SELECT 0 = NULL, NULL<1, NULL<>2;
+----------+--------+---------+
| 0 = NULL | NULL<1 | NULL<>2 |
+----------+--------+---------+
| NULL | NULL | NULL |
+----------+--------+---------+
1 row in set (0.00 sec)

运算符=与<=>均可以用于比较数据是否相等,两者的区别在于后者可以对NULL值进行比较。

mysql> SELECT NULL=NULL, NULL=1, NULL <=> NULL, NULL<=>1;
+-----------+--------+---------------+----------+
| NULL=NULL | NULL=1 | NULL <=> NULL | NULL<=>1 |
+-----------+--------+---------------+----------+
| NULL | NULL | 1 | 0 |
+-----------+--------+---------------+----------+
1 row in set (0.00 sec)

在条件表达式中对指定区间的数据进行判断时,可使用BETWEEN…AND…实现。

BETWEEN 条件1 AND 条件2

匹配模式符“%”可以匹配任意0到多个字符,因此执行结果为4条记录;
若将其修改为“_”表示匹配任意1个字符,上述示例的执行结果就为空,没有符合要求的记录。
在使用时需根据实际的需求具体的选择使用哪种匹配模式符。

正则匹配查询
查询数据时可利用REGEXP关键字指定正则匹配模式轻松完成更为复杂的查询。
正则表达式的语法与其他编程语言相同,读者可自行查看相关的资料进行学习。


符号“|”在正则中表示分隔符,用于分割多种条件,在匹配时只要指定字段满足分隔符左右两边条件中的一个,就表示匹配成功。

关于比较运算,除了比较运算符外,MySQL还提供了很多进行比较运算的函数。

获取categoryid为3或15的商品:
![在这里插入图片描述](https://img-blog.csdnimg.cn/738f1ccaf6884dd494575aa6674818df.png?x-oss-process=image/watermark,typed3F5LXplbmhlaQ,shadow50,textQ1NETiBA5biD6KGj5Lmm55SfLVB5dGhvbg==,size12,colorFFFFFF,t70,gse,x_16)

5.4.3 逻辑运算符

逻辑运算符也是MySQL常用运算符之一,通常应用在条件表达式中的逻辑判断,与比较运算符结合使用。参与逻辑运算的操作数以及逻辑判断的结果只有3种,分别为:

SELECT id, name, price FROM sh_goods
WHERE (keyword, score) = ('电子产品', 5);

在进行逻辑与操作时,若操作数中含有NULL,而另一个操作数若为1(真),则结果为NULL,若另一个操作数为0(假),则结果为0。

mysql> SELECT 1&&NULL, NULL&&1, 0&&NULL, NULL&&0;
+---------+---------+---------+---------+
| 1&&NULL | NULL&&1 | 0&&NULL | NULL&&0 |
+---------+---------+---------+---------+
| NULL | NULL | 0 | 0 |
+---------+---------+---------+---------+
1 row in set (0.00 sec)

逻辑或:只要操作数有一个为真,则运算的结果就为真。


在进行逻辑或操作时,若操作数中含有NULL,而另一个操作数若为1(真),则结果为1;若另一个操作数为0(假),则结果为NULL。

mysql> SELECT 1||NULL, NULL||1, 0||NULL, NULL||0;
+---------+---------+---------+---------+
| 1||NULL | NULL||1 | 0||NULL | NULL||0 |
+---------+---------+---------+---------+
| 1 | 1 | NULL | NULL |
+---------+---------+---------+---------+
1 row in set (0.00 sec)

逻辑非的操作数仅有一个,当操作数为0(假)时,则运算结果为1;当操作数为1(真)时,则运算结果为0;当操作数为NULL时,运算结果为NULL。

mysql> SELECT NOT 10, NOT 0, NOT NULL, NOT 0 + !0, !0 + !0;
+--------+-------+----------+------------+---------+
| NOT 10 | NOT 0 | NOT NULL | NOT 0 + !0 | !0 + !0 |
+--------+-------+----------+------------+---------+
| 0 | 1 | NULL | 0 | 2 |
+--------+-------+----------+------------+---------+
1 row in set (0.00 sec)

逻辑异或操作,表示两个操作数同时都为1或0,则结果为0;若两个操作数一个为
1,一个为0,则结果为1;当操作数为NULL时,则结果为NULL。

mysql> SELECT 1 XOR 2, 0 XOR 0, 0 XOR 2, NULL XOR 2;
+---------+---------+---------+------------+
| 1 XOR 2 | 0 XOR 0 | 0 XOR 2 | NULL XOR 2 |
+---------+---------+---------+------------+
| 0 | 0 | 1 | NULL |
+---------+---------+---------+------------+
1 row in set (0.00 sec)

5.4.4 赋值运算符

MySQL中“=”是一个比较特殊的运算符,既可以用于比较数据是否相等,又可以表示赋值。因此,MySQL为了避免系统分不清楚运算符“=”表示赋值还是比较的含义,特意增加一个符号“:=”用于表示赋值运算。

“=”作为比较运算符时使用:

# “=”作为比较运算符和赋值运算符使用
UPDATE sh_goods SET stock = 1000 WHERE score = 4.5;
# “=”作为比较运算符使用,“:=”作为赋值运算符使用
UPDATE sh_goods SET stock := 1000 WHERE score = 4.5;

在MySQL中,INSERT...SET和UPDATE…SET中出现的运算符“=”都会被认为是赋值运算符。
因此,建议除此之外的其他情况,若需要赋值运算符,推荐使用“:=” ,如为变量赋值。

5.4.5 位运算符

位运算符是针对二进制数的每一位进行运算的符号,运算的结果类型为BIGINT,最大范围可以是64位。


MySQL5.7中参与位运算的数据只能是BIGINT类型(64位的整数),而在MySQL8.0中则允许二进制字符串类型的参数,如BINARY、VARBINARY和BLOB。
因此,MySQL5.7中二进制类型字段的位运算可能在MySQL8.0中产生不同结果,系统也会报相关的警告提示信息。

演示VARBINARY类型的数据位运算

# ① 创建数据表,含有VARBINARY类型的字段
mysql> CREATE TABLE mydb.mybin (b1 VARBINARY(20), b2 VARBINARY(20));
Query OK, 0 rows affected (0.01 sec)
# ② 插入数据
mysql> INSERT INTO mydb.mybin VALUES (2, 6), (3, 1), (4, 9);
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
# ③ 查看数据表中两个字段的按位与、按位或结果
mysql> SELECT b1&b2, b1|b2 FROM mydb.mybin;
+-------+-------+
| b1&b2 | b1|b2 |
+-------+-------+
| 2 | 6 |
| 1 | 3 |
| 0 | 13 |
+-------+-------+
3 rows in set, 2 warnings (0.00 sec)

查看警告信息

mysql> SHOW WARNINGSG
*************************** 1. row ***************************
Level: Warning
Code: 1287
Message: Bitwise operations on BINARY will change behavior in a future version, check the 'Bit functions' section in the manual.
*************************** 2. row ***************************
Level: Warning
Code: 1287
Message: Bitwise operations on BINARY will change behavior in a future version, check the 'Bit functions' section in the manual.
2 rows in set (0.00 sec)

解决位运算的警告问题

mysql> SELECT
-> CAST(b1 AS UNSIGNED) & CAST(b2 AS UNSIGNED) AS one,
-> CAST(b1 AS UNSIGNED) | CAST(b2 AS UNSIGNED) AS two
-> FROM mydb.mybin;
+-----+-----+
| one | two |
+-----+-----+
| 2 | 6 |
| 1 | 3 |
| 0 | 13 |
+-----+-----+
3 rows in set (0.00 sec)

关于位运算,除了位运算符外,MySQL还提供了很多进行位运算的函数。

5.4.6 运算符优先级

运算符优先级可以理解为运算符在一个表达式中参与运算的先后顺序,优先级别越高,则越早参与运算;优先级别越低,则越晚参与运算。



同行的运算符具有相同的优先级,除赋值运算符从右到左运算外,其余相同级别的运算符,在同一个表达式中出现时,运算的顺序为从左到右依次进行。
若要提升运算符的优先级别,可以使用圆括号“()”,当表达式中同时出现多个圆括号时,最内层的圆括号中的表达式优先级最高。

mysql> SELECT 2+3*5, (2+3)*5;
+-------+---------+
| 2+3*5 | (2+3)*5 |
+-------+---------+
| 17 | 25 |
+-------+---------+
1 row in set (0.00 sec)

5.5 总结

本节主要讲了单表的数据操作、排序、分组和聚合等操作,并讲了常见的运算符的用法。

5.6 每日分享

生而为人,要时刻怀揣一颗善良感恩的心,莫以恶小而为之,莫以善小而不为。

展开阅读全文

页面更新:2024-05-20

标签:升序   操作   赋值   表达式   别名   字段   精度   语句   函数   数据表   条件   方式   数据库   商品   数据   列表

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top