MySQL 高级 - 第一章 | 字符集、大小写规范与sql_mode的合理设置

embedded/2024/9/25 7:52:32/

目录

  • 前言
  • 一、字符集
    • 1.1 数据库中的默认字符集
    • 1.2 各级别的字符集
    • 1.3 字符集与比较规则
    • 1.4 字符集设置
    • 1.5 已有库表字符集变更
    • 1.6 请求到响应过程中字符集的变化
  • 二、大小写规范
    • 2.1 Windows 和 Linux 平台区别
    • 2.2 Linux 下大小写规则设置
    • 2.3 SQL 编写建议
  • 三、sql_mode 的合理设置
    • 3.1 sql_mode 的介绍
    • 3.2 sql_mode 常用值
    • 3.3 模式查看与设置


下篇:第二章、数据库目录结构与文件系统

前言

目前市面上使用的 Mysql 大多数都是 mysql-8.0 或者是 mysql-5.7,以下内容是对 mysql 的字符集与大小规范的一个简单介绍

可以用以下命令查看 mysql 版本:

select version();

在这里插入图片描述

如果您想要查看更详细的版本信息,包括版本号、发行版本、系统名称和 description,可以使用以下命令:

SHOW VARIABLES LIKE "%version%";

在这里插入图片描述

以下内容主要源于:bilibili-尚硅谷-MySQL高级篇

MySQL 的安装教程:Linux-安装MySQL(详细教程)


一、字符集

如果使用过 mysql-5.7 的人,大多数都会遇到这样一种情况,就是当我们向数据库中存放一个 emoji 表情 “😃” 时,数据库中的数据是乱码的,如果将该表中的字符集改成 utf8mb4,就能正常存放 emoji 表情 “😃” 了,这个问题就与 mysql 的字符集密切相关


1.1 数据库中的默认字符集

Mysql-8.0 版本之前,默认的字符集为 Iantin1 ,开发人员在进行数据库设置的时候往往会需要将编码修改为 UTF-8 字符集,否则就可能出现乱码的问题

Mysql-8.0 开始,数据库的默认编码改为 utf8mb4,从而避免了上述的问题

通常情况下会使用以下命令查看 mysql 的默认字符集:

show variables like '%character%';

Mysql-8.0 中,默认的字符集如下:

mysql> show variables like '%character%';
+--------------------------+--------------------------------+
| Variable_name            | Value                          |
+--------------------------+--------------------------------+
| character_set_client     | utf8mb4                        |
| character_set_connection | utf8mb4                        |
| character_set_database   | utf8mb4                        |
| character_set_filesystem | binary                         |
| character_set_results    | utf8mb4                        |
| character_set_server     | utf8mb4                        |
| character_set_system     | utf8mb3                        |
| character_sets_dir       | /usr/share/mysql-8.0/charsets/ |
+--------------------------+--------------------------------+
8 rows in set (0.00 sec)

而在 Mysql-5.7 中,默认的字符集如下:

mysql> show variables like '%character%';
+--------------------------+--------------------------------+
| Variable_name            | Value                          |
+--------------------------+--------------------------------+
| character_set_client     | utf8                           |
| character_set_connection | utf8                           |
| character_set_database   | latin1                         |
| character_set_filesystem | binary                         |
| character_set_results    | utf8                           |
| character_set_server     | latin1                         |
| character_set_system     | utf8                           |
| character_sets_dir       | /usr/share/mysql-5.7/charsets/ |
+--------------------------+--------------------------------+
8 rows in set (0.00 sec)
  • character_set_server:服务器级别的字符集
  • character_set_database:当前数据库的字符集
  • character_set_client:服务器解码请求时使用的字符集
  • character_set_connection:服务器处理请求时会把请求字符串从 character_set_client 转换为 character_set_connection
  • character_set_results 服务器向客户端返回数据时使用的字符集

这里主要关注的是 character_set_databasecharacter_set_server


1.2 各级别的字符集

mysql 有 4 个级别的字符集和比较规则,分别是:

  • 服务器级别
    • 定义了 MySQL 服务器实例的默认字符集
    • 可以在 my.cnfmy.ini 配置文件中设置,或使用 SET GLOBAL character_set_server = 'charset_name'; 来动态更改
    • 常见的服务器级别字符集有 utf8、utf8mb4、latin1
  • 数据库级别
    • 定义了特定数据库的默认字符集
    • 当创建数据库时,可以指定字符集,例如 CREATE DATABASE mydb CHARACTER SET utf8mb4;
    • 如果不指定,则使用服务器级别的默认字符集
  • 表级别
    • 定义了表中所有列的默认字符集
    • 创建表时,可以指定字符集,例如 CREATE TABLE mytable (column1 VARCHAR(50)) CHARACTER SET utf8mb4;
    • 如果不指定,则使用数据库级别的默认字符集
  • 列级别
    • 定义了特定列的字符集
    • 创建列时,可以指定字符集,例如 CREATE TABLE mytable (column1 VARCHAR(50) CHARACTER SET utf8mb4);
    • 如果不指定,则使用表级别的默认字符集

1.3 字符集与比较规则

可以通过以下命令查看 mysql 支持的字符集和比较规则:

show charset;

或者

show character set;

示例:

mysql> show character set;
+----------+---------------------------------+---------------------+--------+
| Charset  | Description                     | Default collation   | Maxlen |
+----------+---------------------------------+---------------------+--------+
| armscii8 | ARMSCII-8 Armenian              | armscii8_general_ci |      1 |
| ascii    | US ASCII                        | ascii_general_ci    |      1 |
| big5     | Big5 Traditional Chinese        | big5_chinese_ci     |      2 |
| binary   | Binary pseudo charset           | binary              |      1 |
| cp1250   | Windows Central European        | cp1250_general_ci   |      1 |
| cp1251   | Windows Cyrillic                | cp1251_general_ci   |      1 |
| cp1256   | Windows Arabic                  | cp1256_general_ci   |      1 |
| cp1257   | Windows Baltic                  | cp1257_general_ci   |      1 |
| cp850    | DOS West European               | cp850_general_ci    |      1 |
| cp852    | DOS Central European            | cp852_general_ci    |      1 |
| cp866    | DOS Russian                     | cp866_general_ci    |      1 |
| cp932    | SJIS for Windows Japanese       | cp932_japanese_ci   |      2 |
| dec8     | DEC West European               | dec8_swedish_ci     |      1 |
| eucjpms  | UJIS for Windows Japanese       | eucjpms_japanese_ci |      3 |
| euckr    | EUC-KR Korean                   | euckr_korean_ci     |      2 |
| gb18030  | China National Standard GB18030 | gb18030_chinese_ci  |      4 |
| gb2312   | GB2312 Simplified Chinese       | gb2312_chinese_ci   |      2 |
| gbk      | GBK Simplified Chinese          | gbk_chinese_ci      |      2 |
| geostd8  | GEOSTD8 Georgian                | geostd8_general_ci  |      1 |
| greek    | ISO 8859-7 Greek                | greek_general_ci    |      1 |
| hebrew   | ISO 8859-8 Hebrew               | hebrew_general_ci   |      1 |
| hp8      | HP West European                | hp8_english_ci      |      1 |
| keybcs2  | DOS Kamenicky Czech-Slovak      | keybcs2_general_ci  |      1 |
| koi8r    | KOI8-R Relcom Russian           | koi8r_general_ci    |      1 |
| koi8u    | KOI8-U Ukrainian                | koi8u_general_ci    |      1 |
| latin1   | cp1252 West European            | latin1_swedish_ci   |      1 |
| latin2   | ISO 8859-2 Central European     | latin2_general_ci   |      1 |
| latin5   | ISO 8859-9 Turkish              | latin5_turkish_ci   |      1 |
| latin7   | ISO 8859-13 Baltic              | latin7_general_ci   |      1 |
| macce    | Mac Central European            | macce_general_ci    |      1 |
| macroman | Mac West European               | macroman_general_ci |      1 |
| sjis     | Shift-JIS Japanese              | sjis_japanese_ci    |      2 |
| swe7     | 7bit Swedish                    | swe7_swedish_ci     |      1 |
| tis620   | TIS620 Thai                     | tis620_thai_ci      |      1 |
| ucs2     | UCS-2 Unicode                   | ucs2_general_ci     |      2 |
| ujis     | EUC-JP Japanese                 | ujis_japanese_ci    |      3 |
| utf16    | UTF-16 Unicode                  | utf16_general_ci    |      4 |
| utf16le  | UTF-16LE Unicode                | utf16le_general_ci  |      4 |
| utf32    | UTF-32 Unicode                  | utf32_general_ci    |      4 |
| utf8     | UTF-8 Unicode                   | utf8_general_ci     |      3 |
| utf8mb4  | UTF-8 Unicode                   | utf8mb4_0900_ai_ci  |      4 |
+----------+---------------------------------+---------------------+--------+
41 rows in set (0.00 sec)

Charset 就是所支持的字符集,Description 是描述,Default collation 为对应的比较规则,Maxlen 字段表示所最大占用字节数量

比较规则

在上表中,MySQL 版本一共支持 41 种字符集,其中 Default collation 列表示这种字符集中一种默认的比较规则,里面包含着该比较规则主要作用于哪种语言,比如:uft8_polish_ci 表示以波兰语的规则比较,uft8_spanish_ci 是以西班牙语的规则比较,utf8_general_ci 是一种通用的比较规则。

后缀英文释义描述
_aiaccent insensitive不区分重音
_asaccent sensitive区分重音
_cicase insensitive不区分大小写
_cscase sensitive区分大小写
_binbinary以二进制方式比较

utf8_unicode_ciutf_general_ci 对中、英文来说没有实质性的差别,utf_general_ci 速度较快,但是准确度稍差,utf8_unicode_ci 准确度高,但是速度稍慢,一般情况下用 utf_general_ci 就够了,如果应用中有德语、法语或者是俄语,就需要使用 utf8_unicode_ci

查看 utf8mb4 相关的字符集:

SHOW COLLATION LIKE 'utf8mb4%';

在这里插入图片描述

查看服务器的字符集和比较规则:

SHOW VARIABLES LIKE '%_server';

在这里插入图片描述

查看数据库的字符集和比较规则:

SHOW VARIABLES LIKE '%_database';

在这里插入图片描述

查看具体数据库的字符集和比较规则:

SHOW VARIABLES LIKE '%_database';

如果想要知道某一个数据库创建时是采用哪种字符集或比较规则,可以通过查看建库语句的 sql 查看:

show create database database_name;

在这里插入图片描述

如果想要知道某一个表创建时是采用哪种字符集或比较规则,可以通过查看建表语句的 sql 查看:

show create table table_name;

示例:

mysql> show create table t_access_log;
+--------------+----------------------------------------------------------------------------------------------------------+
| Table        | Create Table                                                                                             |
+--------------+----------------------------------------------------------------------------------------------------------+
| t_access_log | CREATE TABLE `t_access_log` (`id` int NOT NULL AUTO_INCREMENT COMMENT '自增主键',`login_name` varchar(64) DEFAULT NULL COMMENT '登录名',`access_path` varchar(255) DEFAULT NULL COMMENT '访问路径',`access_ip` varchar(16) DEFAULT NULL COMMENT '访问IP',`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`state` tinyint DEFAULT NULL COMMENT '访问状态',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='访问记录表'                   |
+--------------+----------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

utf8 与 utf8mb4 的区别

UTF-8 字符集表示一个字符需要使用 1~4 个字节,通常情况下一些字符只需要 1~3 个字节就可以表示了,而字符集表示一个字符所用的最大字节长度,在某些方面会影响系统的存储和性能,MySQL 的设计者定了两个概念:

  • utf8mb3:阉割的 UTF-8 字符集,只使用 1~3 个字节表示字符
  • uft8mb4:正宗的 UTF-8 字符集,只使用 1~4 个字节表示字符

MySQLutf8utf8mb3 的别名,所以在 MySQL 中使用字符集尽量采用 uft8mb4,比如说前面举例的存入 emoji 表情 “😃” ,就需要使用 uft8mb4


1.4 字符集设置

如果安装的是 mysql-5.7,通常情况下,会在安装好数据库之后修改其配置文件来设置字符集

修改 my.cnf (或者 my.ini)文件,以 linux 上为例:

编辑 my.cnf 文件

vi /etc/my.cnf

[mysqld] 标签下修改配置,例如:

character_set_server=utf8mb4

在这里插入图片描述

修改完配置文件后需要重启下 mysql 服务才会生效

# 启动 mysql
systemctl restart mysqld

在这之后创建的库或者是表就会默认使用 uft8mb4 字符集,但之前创建的库或者表并不会自动修改其字符集


1.5 已有库表字符集变更

修改已创建数据库的字符集:

alter database database_name character set 'utf8mb4';

修改已创建数据库的字符集和比较规则:

alter database database_name character set 'utf8mb4' collate 'utf8_general_ci';

修改已创建数据表的字符集:

alter table table_name convert to character set 'utf8mb4';

修改已创建数据表的字符集和比较规则:

alter table table_name convert to character set 'utf8mb4' collate 'utf8_general_ci';

1.6 请求到响应过程中字符集的变化

从客户端发往服务器的请求本质上就是一个字符串,服务器向客户端返回的结果本质上也是一个字符串,而字符串其实是使用某种字符集编码的二进制数据,从发送请求到返回结果的过程中可能会伴随着多次字符串的转换,其中主要涉及的三个变量如下:

系统变量描述
character_set_client服务器解码请求时使用的字符集
character_set_connection服务器处理请求时会把请求字符串从character_set_client 转为character_set_connection
character_set_results服务器向客户端返回数据时使用的字符集

具体流程如下图所示:

在这里插入图片描述

通常情况下,为了避免多次的字符串转换,通常情况下会将 character_set_clientcharacter_set_connectioncharacter_set_results 这三个系统变量设置成和客户端使用的字符集相一致

例如:

SET character_set_client = 字符集名;
SET character_set_connection = 字符集名;
SET character_set_results = 字符集名;

为了方便我们设置,MySQL 提供了一条非常简便的语句:

SET NAMES 字符集名;

例如:

SET NAMES utf8;

二、大小写规范


2.1 Windows 和 Linux 平台区别

SQL 中,关键字和函数名是不用区分字母大小写的,比如:SELECT、WHERE、ORDER、GROUP BY 等关键字,以及 ABS、MOD、ROUND、MAX 等函数名。

而表名、变量因平台的关系会有所不同,在 WindowsSQL 是不区分大小写的,而在 LinuxSQL 却区分大小写

所以就可能会出现这样一种情况,比如说你的项目中使用了类似于 quartz 这种定时器,在 Windows 上创建的表都是小写,但是一旦迁移到 Linux 上就会出现以下错误:

就是因为两个环境上对大小写敏感度不同所导致的

通常情况下我们可以通过以下命令查看大小写是否敏感:

SHOW VARIABLES LIKE '%lower_case_table_names';
  • Windows 下
mysql> SHOW VARIABLES LIKE '%lower_case_table_names';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| lower_case_table_names | 1     |
+------------------------+-------+
1 row in set (0.00 sec)
  • Linux 下
mysql> SHOW VARIABLES LIKE '%lower_case_table_names';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| lower_case_table_names | 0     |
+------------------------+-------+
1 row in set (0.00 sec)

lower_case_table_names 参数值的设置

  • 0:大小写敏感
  • 1:大小写不敏感,创建的表、数据库都是以小写形式存放在磁盘上,对于 SQL 语句都是转换为小写对表和数据库进行查找
  • 2:创建的表和数据依据语句上的格式存放,凡是查找都是转换为小写进行

所以在 Linux 下会严格区分数据库、表名、表的别名、变量名的大小写,而在 Windows 下都不区分大小写


2.2 Linux 下大小写规则设置

Linux 下如果想要设置为大小写不敏感,mysql-5.7 只要在 my.cnf 文件中的添加或者修改 lower_case_table_names 的值为 1 ,然后再重启数据库即可

这里需要注意的是:在重启数据库之前需要将原来的数据和表名转换为小写,否则将找不到数据库和表

修改 my.cnf (或者 my.ini)文件

在这里插入图片描述

添加以下配置:

[mysqld]  
lower_case_table_names = 1

在这里插入图片描述

接着再重启 mysql

# 重启 mysql
systemctl restart mysqld

但是如果数据库使用的是 mysql-8.0,且数据库已经初始化过了,mysql 是不允许修改大小写敏感的

如果执意要修改可参见博客:MySQL8 设置大小写敏感


2.3 SQL 编写建议

在实际开发中,命名规范建议:

  • ① 关键字和函数名名称全部用大写
  • ② 数据库名、表名、表别名、字段名、字段别名等全部小写
  • SQL 语句必须以分号 ; 结尾

三、sql_mode 的合理设置


3.1 sql_mode 的介绍

sql_mode 会影响 MySQL 支持的 SQL 语法以及它执行的数据验证检查,通过设置 sql_mode 可以完成不同严格程度的数据校验,有效地保障数据的准确性。

MySQL 服务器可以在不同的 SQL 模式下运行,并且可以针对不同的客户端以不同的方式应用这些模式,具体取决于 sql_mode 系统变量的值。

mysql-5.6mysql-5.7 默认的 sql_mode 模式参数是不一样的:

  • mysql-5.6mode 默认为空,即:NO_ENGINE_SUBSTITUTION,其实表示一个空值,相当于没有什么模式设置,可以理解为 宽松模式,在这种设置下可以允许一些非法操作的,比如允许插入一些非法数据的插入
  • mysql-5.7mode 默认为 STRICT_TRANS_TABLES,也就是 严格模式,用于进行数据的严格校验,错误数据不能插入,会报错,并且事务回滚

sql_model 常用来解决下面几类问题:

  • 通过设置 sql_model, 可以完成不同严格程度的数据校验,有效地保障数据准备性

  • 通过设置 sql_model 为宽松模式,来保证大多数 sql 符合标准的 sql 语法,这样应用在不同数据库之间进行迁移时,则不需要对业务 sql 进行较大的修改

  • 在不同数据库之间进行数据迁移之前,通过设置 sql_model 可以使 MySQL 上的数据更方便地迁移到目标数据库中


3.2 sql_mode 常用值

描述
ONLY_FULL_GROUP_BY对于 GROUP BY 聚合操作,如果在 SELECT 中的列,没有在 GROUP BY 中出现,那么这个 SQL 是不合法的,因为列不在 GROUP BY 从句中
NO_AUTO_VALUE_ON_ZERO该值影响自增长列的插入。默认设置下插入 0 或 NULL 代表生成下一个自增长值。如果用户希望插入的值为 0,而该列又是自增长的,那么这个选项就有用了
STRICT_TRANS_TABLES在该模式下,如果一个值不能插入到一个事务表中,则中断当前的操作,对非事务表不做限制
NO_ZERO_IN_DATE在严格模式下,不允许日期和月份为零
NO_ZERO_DATE设置该值,mysql 数据库不允许插入零日期,插入零日期会抛出错误而不是警告
ERROR_FOR_DIVISION_BY_ZERO在 INSERT 或 UPDATE 过程中,如果数据被零除,则产生错误而非警告。如 果未给出该模式,那么数据被零除时 MySQL 返回 NULL
NO_AUTO_CREATE_USER禁止 GRANT 创建密码为空的用户
NO_ENGINE_SUBSTITUTION如果需要的存储引擎被禁用或未编译,那么抛出错误。不设置此值时,用默认的存储引擎替代,并抛出一个异常
PIPES_AS_CONCAT|| 视为字符串的连接操作符而非或运算符,这和 Oracle 数据库是一样的,也和字符串的拼接函数 Concat 相类似
ANSI_QUOTES启用 ANSI_QUOTES 后,不能用双引号来引用字符串,因为它被解释为识别符

3.3 模式查看与设置

如果想要查看当前数据库用的 sql_mode 类型,可通过以下命令进行查看:

select @@session.sql_mode;
# 或者
select @@global.sql_mode;

在这里插入图片描述

临时设置方式:

# 修改当前会话的 sql_mode
set session sql_mode = '';# 修改全局 sql_mode
set global sql_mode = '';

永久设置方式:

my.cnf 或者 my.ini 文件中新增:

[mysqld]
sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

设置完成需要重启 mysql

在实际生产上,一般是采用 临时+永久 结合的方式,临时设置保证当前设置其效果,永久设置保证重启 mysql 之后依然使用所配置的 sql_mode


下篇:第二章、数据库目录结构与文件系统


http://www.ppmy.cn/embedded/32208.html

相关文章

【前端】Layui的表格常用功能,表单提交事件,表格下拉按钮点击事件,表格外的按钮点击事件

欢迎来到《小5讲堂》 大家好,我是全栈小5。 这是《前端》系列文章,每篇文章将以博主理解的角度展开讲解, 特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对知识点的理解和掌握…

BUUCTF:Web 解析(一)

前言 Buuctf Web 是一个在线安全挑战平台,旨在提高参与者对网络安全的理解和实践能力。本文将详细介绍 Buuctf Web 的特点、挑战和机遇,帮助读者更好地了解这一领域。 一、Buuctf Web 的特点 多样化的挑战场景:Buuctf Web 提供了多种挑战场…

MySQL数据库—初识数据库 | DDL语句 | DML语句

初识数据库 ____________________________________★_______________________________________ ▐ 为什么学习数据库? • 以前我们在程序中存储数据. 例如:一个变量,一个对象 ( 数据存储在内存中,程序运行结束后就销毁 ) • …

关于Clion开发stm32printf重定向问题简单解决问题方法

title: 关于Clion开发stm32printf重定向问题简单解决问题方法 tags: STM32Clion 参考来源1 这是另一种方法 在printf 重定向的基础上加上 一句 setbuf(stdout,NULL); 参考来源2 自己写的笔记啦

第IV章-Ⅰ Vue3组件与组件通信

第IV章-Ⅰ Vue3组件与组件通信 Vue组件根组件全局组件局部组件组件模板父子组件 组件间通信子组件获取父组件数据数据传递选项prop传值校验单向数据流 父组件获取子组件数据emit 方法 多级组件通信provide 声明要传递的数据inject 接收数据 总结应用场景单向数据流(…

基于 V2G 技术的电动汽车实时调度策略

基于V2G技术的电动汽车实时调度策略,首先以降低充电成本和网损成本为目标,建立电动汽车调度模型。然后通过构建网损灵敏度指标分析电网节点性能,基于电网负荷制定分时电价,通过潮流计算和凸优化算法实时求解得到电动汽车充放电策略。最后以 IEEE 33 节点配电网为例验证了所…

深度学习之基于Unet肺部CT图像分割项目

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 肺部CT图像分割在医学诊断中占据重要地位,它有助于医生快速、准确地识别和分析肺部病变。…

使用UmcFramework和unimrcpclient.xml连接多个SIP设置的配置指南及C代码示例

使用UmcFramework和unimrcpclient.xml连接多个SIP设置的配置指南及C代码示例 引言1. UniMRCP和UmcFramework简介2. 准备工作3. unimrcpclient.xml配置文件3.1 定义SIP设置3.2 定义MRCP会话配置文件 4. C代码示例5. 测试和验证6. 故障排查7. 结论8. 参考文献 引言 在多媒体通信…