@@ -94,18 +94,173 @@ UTF-8 可以根据不同的符号自动选择编码的长短,像英文字符
94
94
95
95
UTF-32 的规则最简单,不过缺陷也比较明显,对于英文字母这类字符消耗的空间是 UTF-8 的 4 倍之多。
96
96
97
- ** UTF-8** 是目前使用最广的一种字符编码, 。
97
+ ** UTF-8** 是目前使用最广的一种字符编码。
98
98
99
99
![ ] ( https://oss.javaguide.cn/javaguide/1280px-Utf8webgrowth.svg.png )
100
100
101
101
## MySQL 字符集
102
102
103
103
MySQL 支持很多种字符编码的方式,比如 UTF-8、GB2312、GBK、BIG5。
104
104
105
- 你可以通过 ` SHOW CHARSET ` 命令来查看。
105
+ ### 查看支持的字符集
106
+
107
+ 你可以通过 ` SHOW CHARSET ` 命令来查看,支持like和where子句。
106
108
107
109
![ ] ( https://oss.javaguide.cn/javaguide/image-20211008164229671.png )
108
110
111
+ ### 默认字符集
112
+
113
+ 在MySQL5.7中,默认字符集是 ` latin1 ` ;在MySQL8.0中,默认字符集是 ` utf8mb4 `
114
+
115
+ ### 字符集的层次级别
116
+
117
+ MySQL中的字符集有以下的层次级别:
118
+
119
+ - ` server `
120
+ - ` database `
121
+ - ` table `
122
+ - ` column `
123
+
124
+ 它们的优先级可以简单的认为是从上往下依次增大,也即 ` column ` 的优先级会大于 ` table ` 等其余层次的
125
+
126
+ #### server
127
+
128
+ 不同版本的MySQL其 ` server ` 级别的字符集默认值不同,在MySQL5.7中,其默认值是 ` latin1 ` ;在MySQL8.0中,其默认值是 ` utf8mb4 ` 。
129
+
130
+ 当然也可以通过在启动 ` mysqld ` 时指定 ` --character-set-server ` 来设置 ` server ` 级别的字符集。或者如果你是通过源码构建的方式启动的MySQL,你可以在 ` cmake ` 命令中指定选项:
131
+
132
+ ``` sh
133
+ cmake . -DDEFAULT_CHARSET=latin1
134
+ ```
135
+
136
+ 此外,你也可以在运行时改变 ` character_set_server ` 的值,从而达到修改 ` server ` 级别的字符集的目的。
137
+
138
+ ` server ` 级别的字符集可以在我们使用 ` create database ` 语句未指定字符集时被用作默认值,同时它还可能会对连接字符集产生影响,这个可以查看 ** [ ` MySQL Connector/J 8.0 ` 文档] ( https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-charsets.html ) ** 。
139
+
140
+ #### database
141
+
142
+ ` database ` 级别的字符集是我们在创建数据库和修改数据库时指定的:
143
+
144
+ ``` sql
145
+ CREATE DATABASE db_name
146
+ [[DEFAULT] CHARACTER SET charset_name]
147
+ [[DEFAULT] COLLATE collation_name]
148
628C
+
149
+ ALTER DATABASE db_name
150
+ [[DEFAULT] CHARACTER SET charset_name]
151
+ [[DEFAULT] COLLATE collation_name]
152
+ ```
153
+
154
+ 如前面所说,如果在执行上述语句时未指定字符集,那么MySQL将会使用 ` server ` 级别的字符集。这里关于字符集是如何选择的,还有一些比较细致的规则,建议自己翻阅MySQL文档。
155
+
156
+ 可以通过下面的方式查看某个数据库的字符集:
157
+
158
+ ``` sql
159
+ USE db_name;
160
+ SELECT @@character_set_database, @@collation_database;
161
+ ```
162
+
163
+ ``` sql
164
+ SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
165
+ FROM INFORMATION_SCHEMA .SCHEMATA WHERE SCHEMA_NAME = ' db_name' ;
166
+ ```
167
+
168
+ #### table
169
+
170
+ ` table ` 级别的字符集是在创建表和修改表时指定的:
171
+
172
+ ``` sql
173
+ CREATE TABLE tbl_name (column_list)
174
+ [[DEFAULT] CHARACTER SET charset_name]
175
+ [COLLATE collation_name]]
176
+
177
+ ALTER TABLE tbl_name
178
+ [[DEFAULT] CHARACTER SET charset_name]
179
+ [COLLATE collation_name]
180
+ ```
181
+
182
+ 如果在创建表和修改表时未指定字符集,那么将会使用 ` database ` 级别的字符集。这里关于字符集是如何选择的,还有一些比较细致的规则,建议自己翻阅MySQL文档。
183
+
184
+ #### column
185
+
186
+ ` column ` 级别的字符集同样是在创建表和修改表时指定的,只不过它是定义在列中。下面是个例子:
187
+
188
+ ``` sql
189
+ CREATE TABLE t1
190
+ (
191
+ col1 VARCHAR (5 )
192
+ CHARACTER SET latin1
193
+ COLLATE latin1_german1_ci
194
+ );
195
+ ```
196
+
197
+ 如果未指定列级别的字符集,那么将会使用表级别的字符集。这里关于字符集是如何选择的,还有一些比较细致的规则,建议自己翻阅MySQL文档。
198
+
199
+ ### 连接字符集
200
+
201
+ 前面说到了字符集的层次级别,它们是和存储相关的。而连接字符集涉及的是和MySQL服务器的通信。
202
+
203
+ 连接字符集与下面这几个变量息息相关:
204
+
205
+ - ` character_set_client ` (描述了客户端发送给服务器的SQL语句使用的是什么字符集)
206
+ - ` character_set_connection ` (描述了服务器接收到SQL语句时使用什么字符集进行翻译)
207
+ - ` character_set_results ` (描述了服务器返回给客户端的结果使用的是什么字符集)
208
+
209
+ 它们的值可以通过下面的SQL语句查询:
210
+
211
+ ``` sql
212
+ SELECT * FROM performance_schema .session_variables
213
+ WHERE VARIABLE_NAME IN (
214
+ ' character_set_client' , ' character_set_connection' ,
215
+ ' character_set_results' , ' collation_connection'
216
+ ) ORDER BY VARIABLE_NAME;
217
+ ```
218
+
219
+ ``` sql
220
+ SHOW SESSION VARIABLES LIKE ' character\_ set\_ %' ;
221
+ ```
222
+
223
+ 如果要想修改前面提到的几个变量的值,有以下方式:
224
+
225
+ - 修改配置文件
226
+
227
+ 比如加上:
228
+
229
+ ```
230
+ [mysql]
231
+ # 只针对MySQL客户端程序
232
+ default-character-set=utf8mb4
233
+ ```
234
+
235
+ - 使用SQL语句
236
+
237
+ 比如:
238
+
239
+ ``` sql
240
+ set names utf8mb4
241
+ # 或者一个个进行修改
242
+ # SET character_set_client = utf8mb4;
243
+ # SET character_set_results = utf8mb4;
244
+ # SET collation_connection = utf8mb4;
245
+ ```
246
+
247
+ ### jdbc对连接字符集的影响
248
+
249
+ 不知道你们有没有碰到过存储emoji表情正常,但是使用类似Navicat之类的软件的进行查询的时候,发现emoji表情变成了问号的情况。这个问题很有可能就是jdbc驱动引起的。
250
+
251
+ 根据前面的内容,我们知道连接字符集也是会影响我们存储的数据的,而jdbc驱动会影响连接字符集。
252
+
253
+ ` mysql-connector-java ` (jdbc驱动)主要通过这几个属性影响连接字符集:
254
+
255
+ - ` characterEncoding `
256
+ - ` characterSetResults `
257
+
258
+ 以 ` DataGrip 2023.1.2 ` 来说,在它配置数据源的高级对话框中,可以看到 ` characterSetResults ` 的默认值是 ` utf8 ` ,在使用 ` mysql-connector-java 8.0.25 ` 时,连接字符集最后会被设置成 ` utf8mb3 ` 。那么这种情况下emoji表情就会被显示为问号,并且当前版本驱动还不支持把 ` characterSetResults ` 设置为 ` utf8mb4 ` ,不过换成 ` mysql-connector-java driver 8.0.29 ` 却是允许的。
259
+
260
+ 具体可以看一下StackOverflow的 ** [ 这个回答] ( https://stackoverflow.com/questions/54815419/datagrip-mysql-stores-emojis-correctly-but-displays-them-as/76625399#76625399 ) ** 。
261
+
262
+ ### UTF-8使用
263
+
109
264
通常情况下,我们建议使用 UTF-8 作为默认的字符编码方式。
110
265
111
266
不过,这里有一个小坑。
@@ -127,10 +282,10 @@ MySQL 字符编码集中有两套 UTF-8 编码实现:
127
282
128
283
``` sql
129
284
CREATE TABLE `user ` (
130
- ` id` varchar (66 ) CHARACTER SET utf8mb4 NOT NULL ,
131
- ` name` varchar (33 ) CHARACTER SET utf8mb4 NOT NULL ,
132
- ` phone` varchar (33 ) CHARACTER SET utf8mb4 DEFAULT NULL ,
133
- ` password` varchar (100 ) CHARACTER SET utf8mb4 DEFAULT NULL
285
+ ` id` varchar (66 ) CHARACTER SET utf8mb3 NOT NULL ,
286
+ ` name` varchar (33 ) CHARACTER SET utf8mb3 NOT NULL ,
287
+ ` phone` varchar (33 ) CHARACTER SET utf8mb3 DEFAULT NULL ,
288
+ ` password` varchar (100 ) CHARACTER SET utf8mb3 DEFAULT NULL
134
289
) ENGINE= InnoDB DEFAULT CHARSET= utf8;
135
290
```
136
291
@@ -157,3 +312,6 @@ Incorrect string value: '\xF0\x9F\x98\x98\xF0\x9F...' for column 'name' at row 1
157
312
- GB2312-维基百科:< https://zh.wikipedia.org/wiki/GB_2312 >
158
313
- UTF-8-维基百科:< https://zh.wikipedia.org/wiki/UTF-8 >
159
314
- GB18030-维基百科: < https://zh.wikipedia.org/wiki/GB_18030 >
315
+ - MySQL8文档:< https://dev.mysql.com/doc/refman/8.0/en/charset.html >
316
+ - MySQL5.7文档:< https://dev.mysql.com/doc/refman/5.7/en/charset.html >
317
+ - MySQL Connector/J文档:< https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-charsets.html >
0 commit comments