首页 > 解决方案 > PDO 无法使用 COLLATE utf8mb4_unicode_ci 返回 MySQL 搜索

问题描述

我在 MySQL 表上有一个简单的 PHP PDO 查询,它在 phpMyAdmin 控制台中返回一个结果,但无法使用下面的查询返回 PHP 中的任何行... ?

$statement = $this->db->connection->prepare($sql);
$statement->execute();
$arrResults = $statement->fetchAll(PDO::FETCH_ASSOC);

在我的dsn中,我有

;charset=utf8mb4

并且还设置

$this->connection->exec("SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;");

查询的 WHERE 部分如下...注意导致 PDO 问题的“ø”字符。如果我删除它,搜索工作正常。

WHERE (R.last_name LIKE '%Schø%' OR R.first_name LIKE '%Schø%')

或者

WHERE (R.last_name LIKE _utf8mb4 '%Schø%' COLLATE utf8mb4_unicode_ci OR R.first_name LIKE _utf8mb4 '%Schø%' COLLATE utf8mb4_unicode_ci )

phpmyadmin 中返回的结果:
phpmyadmin 中返回的结果

可搜索的列:
可搜索的列

标签: phpmysqlpdoutf8mb4collate

解决方案


我有同样的问题。我已经升级到 PHP 8.0.9 和 MySQL 8.0.26 并且问题已经消失了。我发现这个问题在某种程度上与 PDO 的bindParam调用有关,因为它以某种不正确/不兼容的方式引用了 UTF-8。

我根本没有使用SET NAME utf8mb4call ,而是utf8mb4在 PDO 的 DSN 上指定。

在 MySQL 方面,我将架构/数据库、其表和列设置为utf8mb4_unicode_520_ci(这是最新标准,utf8mb4_unicode_ci应该也可以)。

分享我对我有用的代码,这样你就可以知道什么是真正有效的。

<?php
    $text = 'verbündet';
    try
    {
        $database = 'german';
        $username = 'german';
        $password = 'blaB1A81a';
        $dbh = new PDO("mysql:host=localhost;dbname=".$database.";charset=utf8mb4", $username, $password);
        $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
    catch(PDOException $e)
    {
        echo $e->getMessage();
    }
    try
    {
        $text = strtolower($text);
        $data = [];
        $s = $dbh->prepare("SELECT `word` FROM `words_de` WHERE `word` = :word");
        $s->bindParam(':word', $text, PDO::PARAM_STR);
        $s->execute();
        $fetch = $s->fetch(PDO::FETCH_ASSOC);
        if($fetch === false)
        {
            $data = null;
        }
        else
        {
            $data = $fetch['word'];
        }
    }
    catch(PDOException $e)
    {
        echo $e->getMessage();
    }
?>

推荐阅读