Php 带PDO的UTF-8和latin1混合表格

Php 带PDO的UTF-8和latin1混合表格,php,mysql,character-encoding,pdo,Php,Mysql,Character Encoding,Pdo,存在无法更改字符集的现有数据库/表。这些表使用排序规则“latin1_swedish_ci”,但其中存储有UTF-8数据。例如,字符串“fußball”(德国足球)保存为“fußball”。这是我不能改变的部分 我的整个脚本在UTF-8和它自己的UTF-8表上运行良好,我使用PDO(mySQL)和UTF-8连接进行查询。但有时我不得不查询一些“旧的”拉丁1表。有没有什么“酷”的方法来解决这个问题而不是发送集合名 这是我在stackoverflow的第一个问题!:-) 实际上很容易认为数据是以一

存在无法更改字符集的现有数据库/表。这些表使用排序规则“latin1_swedish_ci”,但其中存储有UTF-8数据。例如,字符串“fußball”(德国足球)保存为“fußball”。这是我不能改变的部分

我的整个脚本在UTF-8和它自己的UTF-8表上运行良好,我使用PDO(mySQL)和UTF-8连接进行查询。但有时我不得不查询一些“旧的”拉丁1表。有没有什么“酷”的方法来解决这个问题而不是发送集合名

这是我在stackoverflow的第一个问题!:-)

  • 实际上很容易认为数据是以一种方式编码的,当它实际以其他方式编码时:这是因为任何直接检索数据的尝试都会导致首先转换为数据库连接的字符集,然后转换为输出介质的字符集,因此您应该首先通过
    SELECT BINARY验证存储数据的实际编码myColumn FROM myTable WHERE…
    从myTable WHERE…
    选择十六进制(myColumn)

  • 一旦确定在Windows-1252编码列中存储了UTF-8编码数据(即,您看到
    0xc39f
    字符
    ß
    ),您真正想要的是从列中删除编码信息,然后告诉MySQL数据实际上编码为UTF-8。如以下文件所述:

    警告
    CONVERT TO
    操作在字符集之间转换列值。如果在一个字符集中有一列(如
    latin1
    ),则这不是您想要的,但存储的值实际上使用了一些其他不兼容的字符集(如
    utf8
    )。在这种情况下,您必须对每个此类列执行以下操作:

    ALTER TABLE t1 CHANGE c1 c1 BLOB; ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8; 更改表t1更改c1 c1 BLOB; 更改表t1更改c1 c1文本字符集utf8; 这种方法之所以有效,是因为在转换到列或从列转换时没有转换

  • 此后,MySQL将根据需要正确地将所选数据转换为连接字符集的数据。也就是说,如果连接使用UTF-8,则不需要转换;而使用Windows-1252的连接将接收转换为该字符集的字符串

  • 不仅如此,MySQL中的字符串比较也将正确执行。例如,如果您当前连接UTF-8字符集并搜索
    “fußball”
    ,则不会得到任何结果;然而,在进行上述修改后,您可能会这样做

  • 您提到的必须更改大量遗留脚本的陷阱仅适用于那些遗留脚本使用不正确的连接字符集的情况(例如,它们告诉MySQL它们使用Windows-1252,而实际上它们正在发送和期望接收UTF-8中的数据)。你真的应该在任何情况下解决这个问题,因为它可能会导致未来的各种恐怖


  • 我通过在我的DB类中创建另一个数据库句柄解决了这个问题,该数据库句柄使用latin1,因此每当我需要查询我可以使用的“遗留表”时

    $pdo    = Db::getInstance();
    $pdo->legacyDbh->query("MY QUERY");
    # instead of
    $pdo->dbh->query("MY QUERY");
    

    如果有人有更好的解决方案,也不要触碰桌子…-)

    为什么您不能更改字符集?因为如果我要更改它,我还必须更改数百个已经运行的脚本:sAt优先,感谢您的详细回复。我执行了步骤1-2,但正如预期的那样,遗留脚本不再工作,因为它们执行了一些utf8_编码/解码/条带斜线/htmlentities。如果不可能正确执行,那么这几乎就是解决方案。数据存储时使用了错误的字符集,使用相同的错误字符集检索数据时,恰好会返回所需的数据。有关原因的解释,请参阅。在继续之前,请使用旧的IBM键盘拍打原始开发人员。只要数据的错误编码在连接字符集中有效,并且此后的任何转换在存储字符集中有效,它就可以工作。这很容易打破,因为对数据的查询会产生意外的结果。