请注意,MySQL的utf8编码最多只有3个字节,无法编码*所有*Unicode字符。
如果您需要编码BMP(基本多语言平面)之外的字符,例如表情符号或其他特殊字符,则需要使用其他编码,例如utf8mb4或任何其他支持更高平面的编码。Mysql将丢弃任何以4个字节(或更多)编码的字符。
有关此问题的更多信息,请参阅https://dev.mysqlserver.cn/doc/refman/5.7/en/charset-unicode-utf8mb4.html
理想情况下,字符集应该在服务器级别设置,MySQL服务器手册的» 字符集配置部分对此进行了描述。或者,每个MySQL API都提供了一种在运行时设置字符集的方法。
应该理解和定义字符集,因为它会影响每个操作,并且包含安全隐患。例如,转义机制(例如,mysqli的mysqli_real_escape_string()和PDO_MySQL的PDO::quote())将遵循此设置。重要的是要意识到这些函数不会使用查询中定义的字符集,因此例如以下操作不会影响它们
示例 #1 使用SQL设置字符集的问题
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
// 不会影响 $mysqli->real_escape_string();
$mysqli->query("SET NAMES utf8mb4");
// 不会影响 $mysqli->real_escape_string();
$mysqli->query("SET CHARACTER SET utf8mb4");
// 但是,这会影响 $mysqli->real_escape_string();
$mysqli->set_charset('utf8mb4');
// 但是,这不会影响它 (UTF-8 vs utf8mb4) -- 不要在这里使用连字符
$mysqli->set_charset('UTF-8');
?>
下面是示例,演示如何使用每个API在运行时正确更改字符集。
注意:可能的UTF-8混淆
因为MySQL中的字符集名称不包含连字符,“utf8”在MySQL中是有效的,用于将字符集设置为UTF-8(最多3字节的UTF-8 Unicode编码)。字符串“UTF-8”无效,因为使用“UTF-8”将无法更改字符集,并将抛出错误。
示例 #2 设置字符集示例:mysqli
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
echo '初始字符集: ' . $mysqli->character_set_name() . "\n";
if (!$mysqli->set_charset('utf8mb4')) {
printf("加载字符集 utf8mb4 失败: %s\n", $mysqli->error);
exit;
}
echo '您当前的字符集是: ' . $mysqli->character_set_name() . "\n";
?>
示例 #3 设置字符集示例:pdo_mysql
<?php
$pdo = new PDO("mysql:host=localhost;dbname=world;charset=utf8mb4", 'my_user', 'my_pass');
?>
请注意,MySQL的utf8编码最多只有3个字节,无法编码*所有*Unicode字符。
如果您需要编码BMP(基本多语言平面)之外的字符,例如表情符号或其他特殊字符,则需要使用其他编码,例如utf8mb4或任何其他支持更高平面的编码。Mysql将丢弃任何以4个字节(或更多)编码的字符。
有关此问题的更多信息,请参阅https://dev.mysqlserver.cn/doc/refman/5.7/en/charset-unicode-utf8mb4.html
设置字符集后,还应该定义“排序规则”,以便提供有关请求结果排序方式的信息。默认情况下,它是“utf8mb4_general_ci”,这是一组简化的排序规则。对于Unicode制定的官方规则,它应该是“utf8mb4_unicode_ci”。
例如
\mysqli_set_charset($hdl, 'utf8mb4');
\mysqli_query($hdl, 'SET collation_connection = utf8mb4_unicode_520_ci');