在php中为utf_unicode_ci准备唯一值

在php中为utf_unicode_ci准备唯一值,php,character-encoding,collation,unique-constraint,Php,Character Encoding,Collation,Unique Constraint,我需要从PHP中的ISO-8859-1编码文件中读取值,并使用PDO将它们写入一个数据库表,该数据库表编码为utf8\u unicode\u ci,并具有唯一索引。有时数据缺少特殊字符,这会导致重复的键错误。示例:数据包含“夹带”和“夹带”。有没有一个PHP字符串函数可以用来避免这种情况 最好是一个转换函数,这样我就不必遍历整个数组来检查是否已经插入了值 下面是我尝试做的一个例子: $values = array("Entraînement", "Entrainement"); $db = ne

我需要从PHP中的ISO-8859-1编码文件中读取值,并使用PDO将它们写入一个数据库表,该数据库表编码为
utf8\u unicode\u ci
,并具有唯一索引。有时数据缺少特殊字符,这会导致重复的键错误。示例:数据包含“夹带”和“夹带”。有没有一个PHP字符串函数可以用来避免这种情况

最好是一个转换函数,这样我就不必遍历整个数组来检查是否已经插入了值

下面是我尝试做的一个例子:

$values = array("Entraînement", "Entrainement");
$db = new PDO("mysql:dbname=mydb;host=localhost;charset=utf8", "user", "pw");
$db->exec("SET NAMES 'UTF-8'");
$stmt = $db->prepare("INSERT INTO mytable(myvalue) VALUES(?)");
$already_inserted = array();
foreach($values as $v) {
    $v = $v_inserted = iconv('iso-8859-1', 'utf-8', $v);
    // Do magic string conversion here
    // $v_inserted = collation_convert($v_inserted)
    if(isset($already_inserted[$v_inserted])) {
        continue;
    }
    if($stmt->execute(array($v))) {
        $already_inserted[$v_inserted] = true;
    }
}

本例只应插入“夹带”,跳过“夹带”

在最初的程序中,我使用ORM而不是PDO,所以我可以在SQL中做很多事情。此外,我在整个拉丁语范围内都有特别的字符-法语、德语、西班牙语等


我无法将DB字段定义更改为
utf8\u bin
,因为它是电子商务软件包的一部分-各种各样的东西都可能会损坏。

那么您肯定应该将值转换为UTF-8并使用UTF-8连接编码。否则,您的应用程序根本无法利用UTF-8,因为您的应用程序只能发送和接收ISO-8859-1包含的字符。与Unicode相比,这是非常非常少的数量☹.


这与您的问题无关*,在
unicode_ci
排序规则中,
unicodeî
被视为与
i
相同。 如果需要将它们视为不同的字符,请使用其他排序规则:

SELECT 'î' = 'i' COLLATE 'utf8_unicode_ci'
//1

SELECT 'î' = 'i' COLLATE 'utf8_bin'
//0
这里没有德语**排序规则,所以我想
utf8\u bin
就是您想要的


*只有当声明的连接编码与发送的物理字节的编码不匹配时,才会出现问题。也就是说,如果您使用UTF-8连接编码发送ISO-8859-1字节,如果不是错误,您将得到垃圾。反之亦然


**我从您的个人资料中查找到,如果您确实需要其他语言,可能会有一个排序规则。

您如何准确读取值,能否显示用于将数据写入表中的代码?谢谢您的建议。我看我可能把我的问题定义得太草率了。我已经扩展了我的问题-现在您可以看到,我可以“在数据库方面做很多事情,并且需要一个PHP函数,它可以执行与MySQL相同的排序字符串比较/转换。@chiborg除非删除唯一约束或更改排序规则,否则无法插入到表中。我建议更改列的排序规则。或者你的意思是在PHP中已经考虑了它们?在这种情况下,您可以使用
intl::Collator::compare
@chiborg仍然不确定您想做什么,但您不能只使用
INSERT IGNORE INTO..
,这样您就不需要在PHP中检查是否插入了内容。它只会默默地失败。