6

我将 varchar 存储在 utf8 MySQL 表中并使用 utf8_general_ci 排序规则。我在 varchar 上有一个唯一索引。我想在 PHP 中做一个字符串比较,这相当于 MySQL 对索引所做的事情。

一个具体的例子是,我希望能够在这种情况发生之前检测到“a”被认为等同于 PHP 中的“À”:

mysql> insert UniTest (str) values ('a');                                   
Query OK, 1 row affected (0.00 sec)

mysql> insert UniTest (str) values ('À');                                   
ERROR 1062 (23000): Duplicate entry 'À' for key 1
4

5 回答 5

9

排序规则与存储无关。您需要设置字符集来确定存储编码。排序规则控制应该如何进行比较和排序。排序规则必须是字符集感知的,否则它与字符集无关。

要回答您的问题,您可以使用iconv转写文本,然后进行比较。例如:

function compare($s1, $s2) {
  return strcmp(
    iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $s1),
    iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $s2));
}

这基本上是 MySql 将为您做的事情,尽管它可能更快,并且它的排序表可能与ISO-8859-1//TRANSLIT. 对此并不完全确定。

正如其他人已经建议的那样,使用数据库可能会更容易。

于 2009-01-23T09:25:57.633 回答
1

通过向 MySQL 提交如下查询,让 MySQL 完成这项工作是否合理:

SELECT CASE WHEN '$a' = '$b' THEN 1 ELSE 0 END


编辑后澄清:

您可以一次性遍历整个感兴趣的笛卡尔字符集,并构建一个标准的 php 等价集关联数组。

    对于 $charset {中的每个 $char1  
        对于 $charset {中的每个 $char2  
            $charmatch[$char1][$char2] = mysqlTestMatch($char1, $char2));  
        }  
    }  

然后你需要逐个字符地测试每个字符串,看看a)它们是否相同,或者如果不是,b)它们是等价的。

于 2009-01-22T22:10:59.993 回答
1

为什么不让 MySQL 决定是否已经存在具有相同键的记录?

您可以运行SELECT查询以询问是否已经有具有此属性的记录:

SELECT 1
FROM UniTest
WHERE str = "À"

或者您只是尝试插入新记录并使用函数mysql_error()mysql_errno()来查看是否发生错误。

于 2009-01-22T22:14:20.343 回答
0

所以,如果我理解正确,您想在 PHP 中进行类似的比较,就像在 MySQL 中检查 UTF-8 通用索引检查一样?

最简单的方法是创建一个辅助函数,根据 MySQL 使用的 utf8_general_ci 规则转换字符串,主要是将某些字母转换为基本字母。

此处列出了该 MySQL 排序规则的规则:

http://www.collation-charts.org/mysql60/mysql604.utf8_general_ci.european.html

例如,如果您向下滚动一点到左侧的“金色 A”,您将看到所有转换为该 A 的字符。

给定一个名为 example 的辅助函数,utf8g_to_ascii()您可以编写一个函数:

function utf8_compare($s1, $s2) {
   $a = utf8g_to_ascii($s1);
   $b = utf8g_to_ascii($s2);
   return strcmp( $a, $b );
}

我将在以下之后建模我的代码:

http://dev.splitbrain.org/view/darcs/dokuwiki/inc/utf8.php
于 2009-02-04T20:33:11.993 回答
0

使用 intl 的 Collat​​or 或 Transliterator。

$s1 = 'a';
$s2 = 'À';

var_dump(
    is_same_string($s1, $s2),
    $s1 === transliterator_transliterate('Any-Latin; Latin-ASCII; Lower()', $s2)
);

function is_same_string($str, $str2, $locale = 'en_US')
{
    $coll = collator_create($locale);
    collator_set_strength($coll, Collator::PRIMARY);  
    return 0 === collator_compare($coll, $str, $str2);
}
于 2013-09-19T07:50:34.953 回答