我将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
答案 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的Collator或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);
}