排序更改后,在多个表中替换多个外来字符

时间:2016-05-23 10:30:41

标签: mysql wordpress collation

我有一个WordPress网站,其中排序规则设置为utf8_unicode_ci,我不得不使用立陶宛字符(Ą ą Č č etc.)。所有这些字符都经过编码和保存,如下面的(Ä„ , Ä… , ÄŒ , Ä etc)

此后我已更改为排序到utf8mb4_unicode_ci,并且所有新记录都已正确保存和显示。但是,所有旧记录的显示方式与数据库(Ä„ , Ä… , ÄŒ , Ä etc)中显示的完全相同。

如何替换多个表中的多个字符以匹配当前的排序规则?

非常感谢任何帮助或指导。

使用更多信息进行编辑

基本上该网站是在不支持的服务器上运行的。在phpMyAdmin的数据库服务器部分,我可以看到以下信息:

Server: Localhost via UNIX socket
Software: MySQL
Software version: 5.1.58-1~dotdeb.0-log - (Debian)
Protocol version: 10
User: srvmtb_mtbWP@localhost
Server charset: UTF-8 Unicode (utf8)

这是旧表的创建表(为清晰起见,删除了大多数字段):

CREATE TABLE IF NOT EXISTS `wp_posts` (
  `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `post_content` longtext COLLATE utf8_unicode_ci NOT NULL,
  `post_title` text COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`ID`),
  KEY `post_name` (`post_name`(191)),
  KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),
  KEY `post_parent` (`post_parent`),
  KEY `post_author` (`post_author`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

以下是在db export上生成INSERT的示例:

INSERT INTO `wp_posts` (`ID`, `post_content`, `post_title`) VALUES
(1, 'Tomas TomĆ„ā€”nas', '');

所以我将这样的整个数据库导出到一个较新的服务器中。这是数据库服务器信息:

Server: Localhost via UNIX socket
Server type: MariaDB
Server version: 10.0.25-MariaDB - MariaDB Server
Protocol version: 10
User: woalba@localhost
Server charset: UTF-8 Unicode (utf8)

更新后,我为每个表运行了以下查询:

ALTER TABLE wp_posts CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

现在,每个新记录都插入并使用正确的字符检索而没有任何问题,但所有旧记录都使用Ć„ā€”这样的奇怪字符进行检索。

如果还有其他重要信息我应该提供 - 请问。

提前致谢。

使用SHOW CREATE TABLE进行编辑

    CREATE TABLE `wp_posts` (  `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `post_author` bigint(20) unsigned NOT NULL DEFAULT '0', 
 `post_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 
 `post_date_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 
 `post_content` longtext COLLATE utf8_unicode_ci NOT NULL,  
`post_title` text COLLATE utf8_unicode_ci NOT NULL,  
`post_excerpt` text COLLATE utf8_unicode_ci NOT NULL, 
 `post_status` varchar(20) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'publish',
  `comment_status` varchar(20) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'open', 
 `ping_status` varchar(20) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'open', 
 `post_password` varchar(20) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
 `post_name` varchar(200) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
 `to_ping` text COLLATE utf8_unicode_ci NOT NULL, 
 `pinged` text COLLATE utf8_unicode_ci NOT NULL,  
`post_modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 
 `post_modified_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 
 `post_content_filtered` longtext COLLATE utf8_unicode_ci NOT NULL, 
 `post_parent` bigint(20) unsigned NOT NULL DEFAULT '0', 
 `guid` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
 `menu_order` int(11) NOT NULL DEFAULT '0', 
 `post_type` varchar(20) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'post',
  `post_mime_type` varchar(100) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
 `comment_count` bigint(20) NOT NULL DEFAULT '0',  PRIMARY KEY (`ID`), 
 KEY `post_name` (`post_name`(191)),  
KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),  
KEY `post_parent` (`post_parent`),  
KEY `post_author` (`post_author`)) ENGINE=MyISAM AUTO_INCREMENT=6394 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

使用SELECT HEX编辑(post_title)

real title is "gegužės 9, 2016 @ 10:16 PM"
post_title = gegužės 9, 2016 @ 10:16 PM
HEX(post_title) = 4F7264657220266E646173683B2067656775C385C2BEC384E280947320392C203230313620402031303A313620504D

1 个答案:

答案 0 :(得分:1)

可能的答案:

生成的INSERT是从mysqldump输出的?它不包括选项--default-character-set=utf8

(我认为,没有证据证明这导致了这个问题。)

你现在有一张桌子上有一些'正确'字母和一些“Mojibake”(例如Ä„)?你想找到并修复Mojibaked行吗?

WHERE col LIKE '%Ä%'可能会找到它。但是,TomĆ„ā€”nas不遵循相同的模式,因此我担心这还不够。

我不知道如何解开Ć“ā€” - 可能是两步甚至三步。

utf8或utf8mb4之前的表是CHARACTER SET?通常Mojibake涉及一些其他字符集(例如latin1)和utf8之间的错误转换。我试过latin2,latin5和latin7;似乎没有工作。

请提供我要求的SELECTs

我不放弃,但这是一个相当大的挑战。

可能的修复

(我说“可能”,因为这可能是也可能不是完整正确的答案。)

首先,测试一下:

SELECT ID,
        CONVERT(BINARY(CONVERT(post_title USING latin1)) USING utf8)
    FROM wp_posts;

查看它是否适用于所有行的post_title。如果您喜欢输出,那么......

UPDATE wp_posts
    SET post_title =
        CONVERT(BINARY(CONVERT(post_title USING latin1)) USING utf8)

证据:

mysql> SELECT CONVERT(BINARY(CONVERT('gegužės 9, 2016 @ 10:16 PM' USING latin1)) USING utf8);
+---------------------------------------------------------------------------------------+
| CONVERT(BINARY(CONVERT('gegužės 9, 2016 @ 10:16 PM' USING latin1)) USING utf8)      |
+---------------------------------------------------------------------------------------+
| gegužės 9, 2016 @ 10:16 PM                                                            |
+---------------------------------------------------------------------------------------+