我可以安全地使用utf8列的utf8mb4连接吗?

the*_*uts 12 php mysql pdo utf-8 utf8mb4

我有一些带有utf8mb4字段的MySQL表,有些带有utf8.

在所有表的PDO连接字符串中使用utf8mb4是安全的吗?或者我必须将所有内容转换为utf8mb4,或启动两个不同的PDO连接?

Pau*_*gel 7

使用以下脚本可以很容易地测试它:

<?php

$pdo = new PDO('mysql:host=localhost;dbname=test', 'test', '');

$pdo->exec("
    drop table if exists utf8_test;
    create table utf8_test(
        conn varchar(50) collate ascii_bin,
        column_latin1  varchar(50) collate latin1_general_ci,
        column_utf8    varchar(50) collate utf8_unicode_ci,
        column_utf8mb4 varchar(50) collate utf8mb4_unicode_ci
    );
");

$latin = 'abc äŒé';
$utf8  = '??';
$mb4   = ' ';

$pdo->exec("set names utf8");

$pdo->exec("
    insert into utf8_test(conn, column_latin1, column_utf8, column_utf8mb4)
     values ('utf8', '$latin', '$latin $utf8', '$latin $utf8 $mb4')
");

$pdo->exec("set names utf8mb4");

$pdo->exec("
    insert into utf8_test(conn, column_latin1, column_utf8, column_utf8mb4)
     values ('utf8mb4', '$latin', '$latin $utf8', '$latin $utf8 $mb4')
");

$result = $pdo->query('select * from utf8_test')->fetchAll(PDO::FETCH_ASSOC);

var_export($result);
Run Code Online (Sandbox Code Playgroud)

结果如下:

array (
  0 => 
  array (
    'conn' => 'utf8',
    'column_latin1' => 'abc äŒé',
    'column_utf8' => 'abc äŒé ??',
    'column_utf8mb4' => 'abc äŒé ?? ???? ????',
  ),
  1 => 
  array (
    'conn' => 'utf8mb4',
    'column_latin1' => 'abc äŒé',
    'column_utf8' => 'abc äŒé ??',
    'column_utf8mb4' => 'abc äŒé ??  ',
  ),
)
Run Code Online (Sandbox Code Playgroud)

如您所见,utf8在使用utf8mb4列时,我们不能将其用作连接字符集(请参阅参考资料????)。但是utf8mb4在使用utf8列时我们可以使用连接。同样,写入latin或读取或读取ascii列也没有问题。

原因是,你可以编码任何utf8latinascii字符utf8mb4而不是周围的其他方式。因此utf8mb4,在这种情况下,将字符集用作连接是安全的。

  • @Dr.GianluigiZaneZanetini - 我怀疑您是否会找到类似“*如果您只使用 Y* 中的字符,则将字符集 X 用于连接,将字符集 Y 用于存储数据是安全的”这样的语句。他们需要为每对字符集编写它。您甚至找不到一条语句,它告诉您可以安全地将 utf8mb4 连接用于 utf8mb4 数据。(不 - 这不是打字错误 - 我的意思是相同的字符集)您需要解释文档。我的解释是我回答的最后一句话。完整阅读 [第 10 章](https://dev.mysql.com/doc/refman/8.0/en/charset.html)。 (2认同)