无法在perl中使用DBI在mysql中插入等效的变音文本

时间:2012-10-11 09:55:50

标签: mysql perl dbi

我有一个列是我的表的主键,它可以有变音符号或普通文本。

我有这两个值:

Håbo and Habo

我想在我的表中插入这两个列值,但是我收到错误:

DBD::mysql::st execute failed: Duplicate entry 'Habo' for key 'PRIMARY'

当我检查Håbo已经插入时,它正在同时处理两个值,因此违反主键。

我的代码:

$dbh = DBI->connect($dsn, $user, $pass)
            or die "Unable to connect: $DBI::errstr\n";
$dbh->{'mysql_enable_utf8'}=1;
$dbh->do('SET NAMES utf8');
my $sql = sprintf "INSERT INTO search_term values(%s, %s)", $dbh->quote($search_term), "Data";

我的表格描述

mysql> desc search_term;
+---------------+--------------+------+-----+---------+-------+
| Field         | Type         | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+-------+
| search        | varchar(200) | NO   | PRI | NULL    |       |
| site          | varchar(500) | NO   |     | NULL    |       |
+---------------+--------------+------+-----+---------+-------+

我如何让MySQL将这两个值视为不同并插入它们? 有什么建议吗?

1 个答案:

答案 0 :(得分:1)

默认情况下,MySQL "helpfully" converts Unicode into their "equivalent" ASCII使用名为Unicode Collation的内容。就像MySQL中的许多“便利”功能一样,如果它告诉你的话会更方便。我不能在这些“话语”周围加上足够的“引号”。

幸运的是,修复非常简单,但并不明显。首先,change the character set of your tables to UTF8所以文本存储在utf8中。然后change the collation to utf8_bin将完全进行比较。我不是100%确定utf8_bin是100%正确的,但它确实有效。

ALTER TABLE search_term CONVERT TO CHARACTER SET utf8;
ALTER TABLE search_term COLLATE utf8_bin;

将来,当您在MySQL中创建表时,请务必append CHARACTER SET utf8 to the creation

CREATE TABLE search_term (
    search varchar(200) primary key,
    site varchar(500)
)
CHARACTER SET utf8
COLLATE       utf8_bin;

最后,所以你不必为每张桌子做这件事,你可以create the database with these defaults already in place

这是good post on the Unicode gotchas in MySQL and their fixes

在Perl端,请务必use utf8,以便传递给MySQL的字符串编码为utf8。

最后,根据DBD::mysql manual,您需要在连接时打开UTF8支持,而不是在之后。如果它发出警告会很好。

Additionally, turning on this flag tells MySQL that incoming data should be
treated as UTF-8. This will only take effect if used as part of the call to
connect(). If you turn the flag on after connecting, you will need to issue
the command SET NAMES utf8 to get the same effect.

将您的连接更改为此。

# I threw in RaiseError because its generally a good idea.
my $dbh = DBI->connect($dsn, $user, $pass, { mysql_enable_utf8 => 1, RaiseError => 1 });