盘点一下Mysql中的一些小知识(五)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 盘点一下Mysql中的一些小知识(五)

union规则

  • UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔(因此,如果组合4条SELECT语句,将要使用3个UNION关键字)。
  • UNION中的每个查询必须包含相同的列、表达式或聚集函数(不过各个列不需要以相同的次序列出)。
  • 列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以隐含地转换的类型(例如,不同的数值类型或不同的日期类型)。

取消重复行

UNION从查询结果集中自动去除了重复的行(换句话说,它的行为与单条SELECT语句中使用多个WHERE子句条件一样)。

mysql> select vend_id,prod_id,prod_price from products where prod_price<=5;
+---------+---------+------------+
| vend_id | prod_id | prod_price |
+---------+---------+------------+
|    1003 | FC      |       2.50 |
|    1002 | FU1     |       3.42 |
|    1003 | SLING   |       4.49 |
|    1003 | TNT1    |       2.50 |
+---------+---------+------------+
4 rows in set (0.00 sec)
mysql> select vend_id,prod_id,prod_price from products where vend_id in (1001,1002);
+---------+---------+------------+
| vend_id | prod_id | prod_price |
+---------+---------+------------+
|    1001 | ANV01   |       5.99 |
|    1001 | ANV02   |       9.99 |
|    1001 | ANV03   |      14.99 |
|    1002 | FU1     |       3.42 |
|    1002 | OL1     |       8.99 |
+---------+---------+------------+
5 rows in set (0.00 sec)
mysql>

分条执行的时候,价格小于等于5的有4条;商品号为(1001,1002)的有4条,使用union后却只有8条?

UNION从查询结果集中自动去除了重复的行(换句话说,它的行为与单条SELECT语句中使用多个WHERE子句条件一样)。因为供应商1002生产的一种物品的价格也低于5,所以两条SELECT语句都返回该行。在使用UNION时,重复的行被自动取消。

使用union all可查看所有匹配行。

mysql>  select vend_id ,prod_id,prod_price
    -> from products
    -> where prod_price <=5
    ->  union all
    ->  select vend_id ,prod_id ,prod_price
    -> from products
    -> where vend_id in(1001,1002);
+---------+---------+------------+
| vend_id | prod_id | prod_price |
+---------+---------+------------+
|    1003 | FC      |       2.50 |
|    1002 | FU1     |       3.42 |
|    1003 | SLING   |       4.49 |
|    1003 | TNT1    |       2.50 |
|    1001 | ANV01   |       5.99 |
|    1001 | ANV02   |       9.99 |
|    1001 | ANV03   |      14.99 |
|    1002 | FU1     |       3.42 |
|    1002 | OL1     |       8.99 |
+---------+---------+------------+
9 rows in set (0.00 sec)

UNION ALL为UNION的一种形式,它完成WHERE子句完成不了的工作。如果确实需要每个条件的匹配行全部出现(包括重复行),则必须使用UNION ALL而不WHERE。

排序

在用UNION组合查询时,只能使用一条ORDER BY子句,它必须出现在最后一条SELECT语句之后。

mysql>  select vend_id ,prod_id,prod_price
    -> from products
    -> where prod_price <=5
    ->  union
    ->  select vend_id ,prod_id ,prod_price
    -> from products
    -> where vend_id in(1001,1002)
    -> order by vend_id,prod_price;
+---------+---------+------------+
| vend_id | prod_id | prod_price |
+---------+---------+------------+
|    1001 | ANV01   |       5.99 |
|    1001 | ANV02   |       9.99 |
|    1001 | ANV03   |      14.99 |
|    1002 | FU1     |       3.42 |
|    1002 | OL1     |       8.99 |
|    1003 | FC      |       2.50 |
|    1003 | TNT1    |       2.50 |
|    1003 | SLING   |       4.49 |
+---------+---------+------------+
8 rows in set (0.00 sec)

全文本搜索

ps:💥这一块强烈建议看书第18章,我已经不知道该怎么写了😭

两个最常使用的引擎为MyISAM和InnoDB,前者支持全文本搜索,而后者不支持。

样例表(productnotes表)使用MyISAM。

image.png

like和正则的限制

  • 性能——通配符和正则表达式匹配通常要求MySQL尝试匹配表中所有行(而且这些搜索极少使用表索引)。这些搜索可能非常耗时。
  • 明确控制——使用通配符和正则表达式匹配,很难(而且并不总是能)明确地控制匹配什么和不匹配什么。
  • 智能化的结果——虽然基于通配符和正则表达式的搜索提供了非常灵活的搜索,但它们都不能提供一种智能化的选择结果的方法。

启用

一般在创建表时启用全文本搜索。CREATE TABLE语句接受FULLTEXT子句,它给出被索引列的一个逗号分隔的列表。

image.png

使用

在索引之后,使用两个函数Match()和Against()执行全文本搜索,其中Match()指定被搜索的列,Against()指定要使用的搜索表达式。

mysql> select note_text from productnotes where match(note_text) against('rabbit');
+-----------------------------------------------------------------------------------------------------------------------+
| note_text
                                            |
+-----------------------------------------------------------------------------------------------------------------------+
| Customer complaint: rabbit has been able to detect trap, food apparently less effective now.                          |
| Quantity varies, sold by the sack load.
All guaranteed to be bright and orange, and suitable for use as rabbit bait. |
+-----------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.01 sec)

此SELECT语句检索单个列note_text。由于WHERE子句,一个全文本搜索被执行。Match(note_text)指示MySQL针对指定的列进行搜索,Against('rabbit')指定词rabbit作为搜索文本。由于有两行包含词rabbit,这两个行被返回。

与like的区别:

mysql> select note_text from productnotes where match(note_text) against('rabbit');

贴代码不美观。。。。。。。。。。。。。。贴图

image.png

这里,在SELECT而不是WHERE子句中使用Match()和Against()。这使所有行都被返回(因为没有WHERE子句)。Match()和Against()用来建立一个计算列(别名为rank),此列包含全文本搜索计算出的等级值。等级由MySQL根据行中词的数目、唯一词的数目、整个索引中词的总数以及包含该词的行的数目计算出来。正如所见,不包含词rabbit的行等级为0(因此不被前一例子中的WHERE子句选择)。确实包含词rabbit的两个行每行都有一个等级值,文本中词靠前的行的等级值比词靠后的行的等级值高。

全文本搜索提供了简单LIKE搜索不能提供的功能。而且,由于数据是索引的,全文本搜索还相当快。

查询扩展

查询扩展不仅会展示所搜索的字符,还会找出可能与搜索相关的所有其他行。利用查询扩展,能找出可能相关的结果,即使它们并不精确包含所查找的词。

  • 首先,进行一个基本的全文本搜索,找出与搜索条件匹配的所有行;
  • 其次,MySQL检查这些匹配行并选择所有有用的词
  • 再其次,MySQL再次进行全文本搜索,这次不仅使用原来的条件,而且还使用所有有用的词。
select note_text from productnotes where match(note_text) against('anvils' with query expansion);

image.png

这次返回了7行。第一行包含词anvils,因此等级最高。第二行与anvils无关,但因为它包含第一行中的两个词(customer和recommend),所以也被检索出来。第3行也包含这两个相同的词,但它们在文本中的位置更靠后且分开得更远,因此也包含这一行,但等级为第三。第三行确实也没有涉及anvils(按它们的产品名)。

布尔文本搜索

以布尔方式,可以提供关于如下内容的细节:

  • 要匹配的词;
  • 要排斥的词
  • 排列提示
  • 表达式分组;
  • 另外一些内容。

布尔方式可不加索引,但非常慢

mysql> select note_text from productnotes where match(note_text) against('heavy' in boolean mode);

为了匹配包含heavy但不包含任意以rope开始的词的行,可使用以下查询:

mysql> select note_text from productnotes where match(note_text) against('heavy -rope*' in boolean mode);

image.png

使用案例:

image.png

使用说明

  1. 在索引全文本数据时,短词被忽略且从索引中排除。短词定义为那些具有3个或3个以下字符的词(如果需要,这个数目可以更改)。
  2. MySQL带有一个内建的非用词(stopword)列表,这些词在索引全文本数据时总是被忽略。如果需要,可以覆盖这个列表(请参阅MySQL文档以了解如何完成此工作)。
  3. 许多词出现的频率很高,搜索它们没有用处(返回太多的结果)。因此,MySQL规定了一条50%规则,如果一个词出现在50%以上的行中,则将它作为一个非用词忽略。50%规则不用于IN BOOLEAN MODE。
  4. 如果表中的行数少于3行,则全文本搜索不返回结果(因为每个词或者不出现,或者至少出现在50%的行中)。
  5. 忽略词中的单引号。例如,don't索引为dont。
  6. 不具有词分隔符(包括日语和汉语)的语言不能恰当地返回全文本搜索结果。(很可惜~~)
  7. 如前所述,仅在MyISAM数据库引擎中支持全文本搜索。

插入数据

单行插入

insert into 表名(列名) values (对应的值);

对于完整写法来说,每一列必须一一对应每一个值。否则插入会出问题。(可根据需要选择列)

insert into 表名 values (值);

省略写法,默认对应所有的列,即value值也必须对应所有的列。

多行插入

  1. 多条insert语句
  2. 多个value项

insert into 表名(列名) values (对应的值),(对应的值),(对应的值)......;

MySQL用单条INSERT语句处理多个插入比使用多条INSERT语句快。

插入检索出的数据

假如你想从另一表中合并客户列表到你的customers表。不需要每次读取一行,然后再将它用INSERT插入,可以使用INSERT SELECT:(这道题面试我就遇上了😭)

  1. 准备一张和customers相同结构的表custnew
  2. 给custnew 填充数据,注意主键不能重复,否则会插入失败
mysql> insert into customers 
    select * from custnew;
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

超级简写形式,因为懒😂

正常应列出所有的列

不一定要求列名匹配,它使用的是列的位置,因此SELECT中的第一列(不管其列名)将用来填充表列中指定的第一个列,第二列将用来填充表列中指定的第二个列,如此等等。

更新和删除

更新

  • 更新表中特有的行
  • 更新表中所有的行

两者的区别在于语句中是否有where来限制范围。

更新客户1005的电子邮箱:

mysql> update customers set cust_email = 'abc@qq.com'
    -> where cust_id =1005;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0  Changed: 0  Warnings: 0

❗️❗️where子句非常重要,没有就更新整张表了

更新多列:

mysql> update customers 
set cust_email = 'abc@qq.com',
cust_name = 'test_update'
where cust_id =1005;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0  Changed: 0  Warnings: 0

如果用UPDATE语句更新多行,并且在更新这些行中的一行或多行时出一个现错误,则整个UPDATE操作被取消(错误发生前更新的所有行被恢复到它们原来的值)。为即使是发生错误,也继续进行更新,可使用IGNORE关键字,如下所示:

UPDATE IGNORE customers…

删除

  • 删除表中特定的行
  • 删除表中所有的行

两者的区别在于语句中是否有where来限制范围。

删除某一行:

mysql> delete from customers where cust_id = 1006;
Query OK, 0 rows affected (0.00 sec)

如果没有where子句,那么将删除所有行。

如果想从表中删除所有行,不要使用DELETE。可使用TRUNCATE TABLE语句,它完成相同的工作,但速度更快(TRUNCATE实际是删除原来的表并重新创建一个表,而不是逐行删除表中的数据)。

创建和操作表

创建表

CREATE TABLE `customers` (
  `cust_id` int(11) NOT NULL AUTO_INCREMENT,
  `cust_name` char(50) NOT NULL,
  `cust_address` char(50) DEFAULT NULL,
  `cust_city` char(50) DEFAULT NULL,
  `cust_state` char(5) DEFAULT NULL,
  `cust_zip` char(10) DEFAULT NULL,
  `cust_country` char(50) DEFAULT NULL,
  `cust_contact` char(50) DEFAULT NULL,
  `cust_email` char(255) DEFAULT NULL,
  PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB;


CREATE TABLE 表名(
    字段值  字段类型  是否为空(NULL|NOT NULL) 默认值(default xx)AUTO_INCREMENT(int主键自动递增),
    ....
    PRIMARY KEY (`字段值`) #指定主键
)ENGINE = 选择引擎类型;

更新表

#添加一列:
alter table 表名  add  列名  类型;
#删除一列:
alter table 表名 drop column 列名;
#定义外键:
alter table orderitems
add constant fk_orderitems_orders
foreign key (order_num) references orders(order_num);

删除表

drop table 表名;

重命名

rename table 表名 to 更新后名字;


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
关系型数据库 MySQL 数据安全/隐私保护
Mysql
Mysql
49 0
|
存储 SQL 算法
盘点一下Mysql中的一些小知识(三)
盘点一下Mysql中的一些小知识(三)
94 0
盘点一下Mysql中的一些小知识(三)
|
SQL 安全 关系型数据库
|
关系型数据库 MySQL
MySQL一行变多行,多行变一行
MySQL一行变多行,多行变一行
196 1
MySQL一行变多行,多行变一行
|
JSON 算法 关系型数据库
MySQL 8.0.32如期而至
MySQL 8.0版本计划 MySQL 8.0开始采用快速迭代开发模式,基本上是每隔3个月就发布一个新的小版本。去年1月18日(2022.1.18)发布MySQL 8.0.28,今年1月17日发布MySQL 8.0.32,再看看其他几个版本的时间,还真是贼守时啊。
363 0
|
关系型数据库 MySQL
07_mysql中having的使用_having与where的对比
mysql中having的使用 having与where的对比
180 0
07_mysql中having的使用_having与where的对比
|
SQL 关系型数据库 MySQL
mysql
在表中插入数据
109 0
|
存储 SQL 关系型数据库
Mysql(三)
Mysql(三)
142 0
Mysql(三)
|
存储 SQL 自然语言处理
MySQL必知必会
MySQL必知必会 29
163 0
MySQL必知必会
|
存储 SQL 安全
MySQL 是什么
MySQL 是什么
354 0