【问题标题】:MySQL/PDO truncates the dataMySQL/PDO 截断数据
【发布时间】:2012-07-25 08:12:43
【问题描述】:

$book 是一个 7kb 的字符串。如果使用 PHP PDO exec 执行此查询,monograph 列 (LONGTEXT) 数据将在 6765 个字符处被截断:

echo strlen($book); // output 7157

$db->exec("UPDATE `chemicals` SET `monograph` = {$db->quote($book)} WHERE `id` = {$db->quote($c['id'])};");

但是,如果我打印查询并使用 SQL 客户端(绕过 PHP)执行它,它会将所有数据插入数据库。这让我觉得这是我还不熟悉的 PHP 设置。

请注意,如果我使用准备好的语句(包括使用 PDO::PARAM_LOB),也会发生同样的情况。

$book 值在 exec https://gist.github.com/79d5fe1050bbb0e2fac8 (7157) 之前转储。最终到达数据库 https://gist.github.com/df49d4a9707660b8b60b (6765) 的实际数据。我不明白这种数据截断在技术上是如何实现的,因为整个查询都传递给 MySQL(否则会弹出 SQL 语法错误)。

echo "UPDATE `chemicals` SET `monograph` = {$db->quote($book)} WHERE `id` = {$db->quote($c['id'])};";

如果我使用 SQL 客户端执行输出 (https://gist.github.com/a05fe4c033e74897b82b),这就是数据库中的数据 https://gist.github.com/88870fe26a3ae40e991e(预期为 7157)。

使用 UTF8 连接启动 PDO。

new PDO('mysql:dbname=[..];host=localhost;charset=utf8', 'root', '[..]', array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8' COLLATE 'utf8_unicode_ci';"));

更新 2012 年 7 月 25 日 04:11 EST

现在我知道这是编码问题。

$db->exec("UPDATE `chemicals` SET `monograph` = {$db->quote(utf8_decode($book))} WHERE `id` = {$db->quote($c['id'])};");

但是,我不确定该怎么做。我与 MySQL 的连接已经是 unicode。

/etc/my.cnf 配置为在服务器范围内使用以下设置。

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

【问题讨论】:

  • 数据被截断为一个奇怪的(非 ASCII)字符。您是否正确设置了连接字符集?
  • @eggyal 连接是 utf8 与整理 utf8_general_ci 服务器范围。
  • 确认一下,你是如何设置连接字符集的?字符串肯定是用 UTF-8 编码的吗?数据被截断时的字节序列是什么?

标签: mysql pdo mysqlnd


【解决方案1】:

这里有两点需要说明。一是理想情况下,所有字符编码都必须是UTF8——即服务器、客户端、连接和表。二是PHP的strlen函数计算字节数,而不是字符数。

您的表格字符集可能未设置为UTF8。你可以这样做

SHOW CREATE TABLE chemicals;

检查。您还应该将这些添加到您的my.cnf

[mysqld]
character-set-client=utf8
character-set-results=utf8

在此处阅读有关 MySQL 字符集的更多信息:

MySQL character sets

【讨论】:

  • 与 MySQL 相关的一切都在使用 unicode。 gist.github.com/98f79ad868a1d5fb77b2 但是,输入数据不是 unicode。
  • 表列编码也是utf8?如果您的输入数据不是utf8,那么 MySQL 正在对其进行字符转换,您不应该期望长度匹配。查看您的输入数据,其中至少有一个非 ASCII 字符(看起来像 U+FFFD,unicode 替换字符。)
【解决方案2】:

原来是编码问题。这是两个解决方案。最明显的是修复编码以匹配数据库/连接设置。就我而言,我得到了一个 iso-8859-1 字符串并将其解释为 unicode。

但是,无论如何,这应该不是问题。我进一步发现PDO::ATTR_EMULATE_PREPARES默认设置为TRUE。

【讨论】:

    猜你喜欢
    • 2014-08-26
    • 1970-01-01
    • 1970-01-01
    • 2013-10-14
    • 1970-01-01
    • 1970-01-01
    • 2015-10-15
    • 2012-06-02
    • 1970-01-01
    相关资源
    最近更新 更多