学习 MySQL 需要知道的 28 个小技巧
Posted Lucifer三思而后行
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习 MySQL 需要知道的 28 个小技巧相关的知识,希望对你有一定的参考价值。
前言
随着信息技术的不断发展以及互联网行业的高速增长,作为开源数据库的mysql得到了广泛的应用和发展。目前MySQL已成为关系型数据库领域中非常重要的一员。
无论是运维、开发、测试,还是架构师,数据库技术都是一个 必备加薪神器
,那么,一直说学习数据库、学 MySQL
,到底是要学习它的哪些东西呢?
一、如何快速掌握 MySQL?
培养兴趣
兴趣是最好的老师,不论学习什么知识,兴趣都可以极大地提高学习效率。不管学习 MySQL5.7
还是 MySQL8.0
都不例外!
夯实 SQL 基础
计算机领域的技术非常强调基础,刚开始学习可能还认识不到这一点。随着技术应用的深 入,只有有着扎实的基础功底,才能在技术的道路上走得更快、更远。对于 MySQL 的学习来说, SQL 语句 是其中最为基础的部分,很多操作都是通过 SQL 语句来实现的。所以在学习的过程中, 读者要多编写 SQL 语句,对于同一个功能,使用不同的实现语句来完成,从而深刻理解其不同之处。
🏆 这里可以参考文章:基础篇:数据库 SQL 入门教程
及时学习新知识
正确、有效地利用搜索引擎,可以搜索到很多关于 MySQL 的相关知识。同时,参考别 人解决问题的思路,也可以吸取别人的经验,及时获取最新的技术资料。
多实践操作
数据库系统具有极强的操作性,需要多动手上机操作。在实际操作的过程中才能发现问题, 并思考解决问题的方法和思路,只有这样才能提高实战的操作能力。
二、技巧分享
下面分享学习 MySQL 的 28 个不得不知道的小技巧!
1、MySQL 中如何使用特殊字符?
诸如单引号 '
,双引号 "
,反斜线 \\
等符号,这些符号在 MySQL 中不能直接输入使用,否则会产生意料之外的结果。
举例:
假设 Lucifer 表中需要存入一行记录,值为 lucifer's dog
,其中的单引号 '
号,如果不做转义,则无法成功执行:
mysql> create table lucifer (id int,name char(100));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into lucifer values (1,'lucifer's dog');
'>
'> mysql>
^C
mysql>
在 MySQL 中,这些特殊字符称为转义字符,在输入时需要以反斜线符号 \\
开头,所以在使用单引号和双引号时应分别输入 \\'
或者 \\"
,输入反斜线时应该输入 \\\\
,其他特殊字符还有回车符 \\r
,换行符 \\n
,制表符 \\tab
,退格符 \\b
等。
mysql> create table lucifer (id int,name char(100));
Query OK, 0 rows affected (0.03 sec)
mysql> insert into lucifer values (1,'lucifer\\'s dog');
Query OK, 1 row affected (0.00 sec)
mysql> select * from lucifer;
+------+---------------+
| id | name |
+------+---------------+
| 1 | lucifer's dog |
+------+---------------+
1 row in set (0.00 sec)
mysql>
📢 注意: 在向数据库中插入这些特殊字符时,一定要进行转义处理。
2、MySQL 中可以存储文件吗?
答案当然是可以的!
MySQL 中的 BLOB
和 TEXT
字段类型可以存储数据量较大的文件,可以使用这些数据类型 存储图像、声音或者是大容量的文本内容,例如网页或者文档。
mysql> create table view(id int unsigned NOT NULL AUTO_INCREMENT, catid int,title varchar(256),picture MEDIUMBLOB, content TEXT,PRIMARY KEY (id));
Query OK, 0 rows affected (0.03 sec)
mysql> show fields from view;
+---------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| catid | int | YES | | NULL | |
| title | varchar(256) | YES | | NULL | |
| picture | mediumblob | YES | | NULL | |
| content | text | YES | | NULL | |
+---------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
mysql>
虽然使用 BLOB 或者 TEXT 可 以存储大容量的数据,但是对这些字段的处理会降低数据库的性能。
📢 注意: 如果并非必要,可以选择只储存文件的路径。
3、MySQL 中如何执行区分大小写的字符串比较?
MySQL 是 不区分大小写
的,因此字符串比较函数也不区分大小写。
mysql> select 'TRUE' from dual where 'DOG' = 'dog';
+------+
| TRUE |
+------+
| TRUE |
+------+
1 row in set (0.00 sec)
如果想执行区分大小写的比较,可以在字符串前面添加 BINARY 关键字。
mysql> select 'TRUE' from dual where BINARY'DOG' = 'dog';
Empty set (0.00 sec)
mysql>
例如默认情况下,’DOG‘=’dog‘ 返回结果为 TRUE,如果使用 BINARY 关键字,BINARY’DOG’=‘dog’ 结果为 FALSE,在区分大小写的情况下,’DOG’ 与 ’dog’ 并不相同。
4、如何从日期时间值中获取年、月、日等部分日期或时间值?
MySQL 中,日期时间值以字符串形式存储在数据表中,因此可以使用字符串函数分别截取日期时间值的不同部分。
mysql> create table lucifer(date date);
Query OK, 0 rows affected (0.04 sec)
mysql> show fields from lucifer;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| date | date | YES | | NULL | |
+-------+------+------+-----+---------+-------+
1 row in set (0.00 sec)
mysql> insert into lucifer values (now());
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select * from lucifer;
+------------+
| date |
+------------+
| 2021-11-25 |
+------------+
1 row in set (0.00 sec)
例如某个名称为 date 的字段有值 2021-11-25
,如果只需要获得年值,可以输入 LEFT(date, 4)
,这样就获得了字符串左边开始长度为 4 的子字符串,即 YEAR
部分的值;
mysql> select LEFT(date, 4) from lucifer;
+---------------+
| LEFT(date, 4) |
+---------------+
| 2021 |
+---------------+
1 row in set (0.00 sec)
如果要获取月份值,可以输入 MID(date,6,2)
,字符串第 6 个字符开始,长度为 2 的子字符串正好为 date 中的月份值。同理,读者可以根据其他日期和时间的位置,计算并获取相应的值。
mysql> select MID(date,6,2) from lucifer;
+---------------+
| MID(date,6,2) |
+---------------+
| 11 |
+---------------+
1 row in set (0.00 sec)
5、如何改变默认的字符集?
CONVERT()
函数改变指定字符串的默认字符集!
MySQL 的安装和配置过程中,其中的一个步骤是可以选择 MySQL 的默认字符集。但是,如果只改变字符集,没有必要把配置过程重新执行一遍,在这里,一个简单的方式是 修改配置文件
。
读者可以在修改字符集时使用 SHOW VARIABLES LIKE 'character_set_%';
或者 status
命令查看当前字符集,以进行对比。
mysql> SHOW VARIABLES LIKE 'character_set_%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | utf8mb3 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | utf8mb4 |
| character_set_system | utf8mb3 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)
mysql> status
--------------
mysql Ver 8.0.26-0ubuntu0.21.04.3 for Linux on aarch64 ((Ubuntu))
Connection id: 10
Current database:
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 8.0.26-0ubuntu0.21.04.3 (Ubuntu)
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: utf8mb4
Db characterset: utf8mb4
Client characterset: latin1
Conn. characterset: latin1
UNIX socket: /var/run/mysqld/mysqld.sock
Binary data as: Hexadecimal
Uptime: 36 min 55 sec
Threads: 2 Questions: 325 Slow queries: 0 Opens: 181 Flush tables: 3 Open tables: 69 Queries per second avg: 0.146
--------------
mysql>
MySQL 配置文件名称为 my.cnf
,该文件在 MySQL 的安装目录下面。修改配置文件中的 default-character-set
和 character-set-server
参数值,将其改为想要的字符集名称,如 gbk、gb2312、latinl 等,修改完之后重新启动 MySQL 服务,即可生效。
## 找到 my.cnf 位置
root@modb:~# find /etc -iname my.cnf -print
/etc/alternatives/my.cnf
/etc/mysql/my.cnf
## 修改字符集
在[client ]下面加入
default-character-set=utf8
在[ mysqld ] 下面加
character_set_server=utf8
## 重启 mysql 生效
service mysql restart
此时,登录 MySQL 后使用 SHOW VARIABLES LIKE 'character_set_%';
或者 status
命令查看修改结果!
6、DISTINCT 可以应用于所有的列吗?
查询结果中,如果需要对列进行降序排序,可以使用 DESC
,这个关键字只能对其前面的列 进行降序排列。
mysql> select * from lucifer;
+------+----------+
| id | name |
+------+----------+
| 1 | lucifer |
| 2 | lucifer1 |
| 3 | lucifer2 |
+------+----------+
3 rows in set (0.00 sec)
mysql> select * from lucifer order by id desc;
+------+----------+
| id | name |
+------+----------+
| 3 | lucifer2 |
| 2 | lucifer1 |
| 1 | lucifer |
+------+----------+
3 rows in set (0.00 sec)
例如,要对多列都进行降序排序,必须要在每一列的列名后面加 DESC
关键字。
mysql> select * from lucifer order by id desc,name desc;
+------+----------+
| id | name |
+------+----------+
| 3 | lucifer2 |
| 2 | lucifer1 |
| 1 | lucifer |
+------+----------+
3 rows in set (0.00 sec)
而 DISTINCT
不同,DISTINCT 不能部分使用。换句话说,DISTINCT 关键字应用于所有列而不仅是它后面的第一个指定列。
例如,查询 2 个字段 sex,age,如果不同记录的这 2 个字段的组合值都不同,则所有记录都会被查询出来。
mysql> select * from lucifer;
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoli | male | 20 |
| 1 | xiaoliu | female | 21 |
| 1 | xiaozhang | female | 21 |
| 1 | xiaowu | female | 21 |
+------+-----------+--------+------+
4 rows in set (0.00 sec)
mysql> select distinct sex,age from lucifer;
+--------+------+
| sex | age |
+--------+------+
| male | 20 |
| female | 21 |
+--------+------+
2 rows in set (0.00 sec)
mysql>
7、ORDER BY 可以和 LIMIT 混合使用吗?
在使用 ORDER BY 子句时,应保证其位于 FROM 子句之后,如果使用 LIMIT
,则必须位于 ORDER BY
之后,如果子句顺序不正确,MySQL 将产生错误消息。
✅ 正确用法:
mysql> select * from lucifer order by age desc limit 2,4;
+------+--------+--------+------+
| id | name | sex | age |
+------+--------+--------+------+
| 1 | xiaowu | female | 21 |
| 1 | xiaoli | male | 20 |
+------+--------+--------+------+
2 rows in set (0.00 sec)
❎ 错误用法:
mysql> select * from lucifer limit 2,4 order by age desc;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'order by age desc' at line 1
mysql>
8、什么时候使用引号?
在查询的时候,会看到在 WHERE 子句中使用条件,有的值加上了单引号,而有的值未加。
mysql> select * from lucifer where sex = 'female';
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoliu | female | 21 |
| 1 | xiaozhang | female | 21 |
| 1 | xiaowu | female | 21 |
+------+-----------+--------+------+
3 rows in set (0.00 sec)
mysql>
单引号用来限定字符串,如果将值与字符串类型列进行比较,则需要限定引号;而用来与数值进行比较则不需要用引号。
mysql> select * from lucifer where age = 20;
+------+--------+------+------+
| id | name | sex | age |
+------+--------+------+------+
| 1 | xiaoli | male | 20 |
+------+--------+------+------+
1 row in set (0.00 sec)
mysql>
9、在 WHERE子句中 AND 和 OR 必须使用圆括号吗?
任何时候使用具有 AND
和 OR
操作符的 WHERE
子句,都应该使用圆括号明确操作顺序。
mysql> select * from lucifer where (age = 20 or sex = 'female') and name != 'xiaowu';
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoli | male | 20 |
| 1 | xiaoliu | female | 21 |
| 1 | xiaozhang | female | 21 |
+------+-----------+--------+------+
mysql> 3 rows in set (0.00 sec)
如果条件较多,即使能确定计算次序,默认的计算次序也可能会使 SQL 语句不易理解,因此使 用括号明确操作符的次序,是一个好的习惯。
10、更新或者删除表时必须指定 WHERE子 句吗?
个人建议所有的 UPDATE 和 DELETE 语句全都在 WHERE 子句中指定条件。
mysql> update lucifer set age = 22 where name = 'xiaoliu';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from lucifer where name = 'xiaoliu';
+------+---------+--------+------+
| id | name | sex | age |
+------+---------+--------+------+
| 1 | xiaoliu | female | 22 |
+------+---------+--------+------+
1 row in set (0.00 sec)
mysql>
如果省略 WHERE 子句,则 UPDATE 或 DELETE 将被应用到表中所有的行。
mysql> update lucifer set age = 22;
Query OK, 3 rows affected (0.01 sec)
Rows matched: 4 Changed: 3 Warnings: 0
mysql> select * from lucifer;
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoli | male | 22 |
| 1 | xiaoliu | female | 22 |
| 1 | xiaozhang | female | 22 |
| 1 | xiaowu | female | 22 |
+------+-----------+--------+------+
4 rows in set (0.00 sec)
mysql>
因此,除非确实打算更新或者删除所有记录,否则要注意使用不带 WHERE 子句的 UPDATE 或 DELETE 语句。
📢 注意: 建议在对表进行更新和删除操作之前,使用 SELECT 语句确认需要删除的记录,以免造成无法挽回的结果。
11、索引对数据库性能如此重要,应该如何使用它?
索引的优点:
- 通过创建唯一索引可以保证数据库表中每一行数据的唯一性。
- 可以给所有的 MySQL 列类型设置索引。
- 可以大大加快数据的查询速度,这是使用索引最主要的原因。
- 在实现数据的参考完整性方面可以加速表与表之间的连接。
- 在使用分组和排序子句进行数据查询时也可以显著减少查询中分组和排序的时间
缺点:
- 创建和维护索引组要耗费时间,并且随着数据量的增加所耗费的时间也会增加。
- 索引需要占磁盘空间,除了数据表占数据空间以外,每一个索引还要占一定的物理空间。如果有大量的索引,索引文件可能比数据文件更快达到最大文件尺寸。
- 当对表中的数据进行增加、删除和修改的时候,索引也要动态维护,这样就降低了数据的维护速度。
使用索引时,需要综合考虑索引的优点和缺点。
为数据库选择正确的索引是一项复杂的任务。如果索引列较少,则需要的磁盘空间和维护开销 都较少。如果在一个大表上创建了多种组合索引,索引文件也会膨胀很快。
而另一方面,索引较多 可覆盖更多的查询。可能需要试验若干不同的设计,才能找到最有效的索引。可以添加、修改和删 除索引而不影响数据库架构或应用程序设计。
因此,应尝试多个不同的索引从而建立最优的索引。
12、尽量使用短索引(前缀索引)
对字符串类型的字段进行索引,如果可能应该指定一个前缀长度。
例如,如果有一个 CHAR(255) 的列,如果在前 10 个或 30 个字符内,多数值是惟一的,则不需要对整个列进行索引。
mysql> select * from lucifer;
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoli | male | 22 |
| 1 | xiaoliu | female | 22 |
| 1 | xiaozhang | female | 22 |
| 1 | xiaowu | female | 22 |
+------+-----------+--------+------+
4 rows in set (0.00 sec)
mysql> create index idx_lucifer_name on lucifer (name(4));
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show index from lucifer;
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------以上是关于学习 MySQL 需要知道的 28 个小技巧的主要内容,如果未能解决你的问题,请参考以下文章