用PHP比较PHP中的字符串

时间:2009-01-22 22:05:48

标签: php mysql utf-8 collation mysql-error-1062

我将varchar存储在utf8 MySQL表中并使用utf8_general_ci排序规则。我在varchar上有一个唯一的索引。我想在PHP中进行字符串比较,这与MySQL在索引上的操作相同。

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

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

5 个答案:

答案 0 :(得分:9)

排序规则与存储无关。您需要设置charset以确定存储编码。整理控制着如何进行比较和排序。整理必须是charset意识,否则它与charset无关。

要回答您的问题,您可以使用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略有不同。不完全确定。

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

答案 1 :(得分:1)

通过向MySQL提交查询来让MySQL完成工作是否合理:

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

<小时/> 编辑后澄清:

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

    for each $char1 in $charset {  
        for each $char2 in $charset {  
            $charmatch[$char1][$char2] = mysqlTestMatch($char1, $char2));  
        }  
    }  

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

答案 2 :(得分:1)

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

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

SELECT 1
FROM UniTest
WHERE str = "À"

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

答案 3 :(得分:0)

所以,如果我正确地得到它,你想在PHP中进行类似的比较,就像你在MySQL中对UTF-8一般索引检查进行检查一样吗?

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

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

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

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

给定一个辅助函数,例如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

答案 4 :(得分: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);
}