PHP,MySQL中带有utf8数据的奇怪排序问题 [英] Strange sorting problem in PHP, mysql with utf8 data
问题描述
我的一个数据库表有一个非常奇怪的问题.我将各个区域归类为区域(区域A,区域B等),当我运行查询以在下拉菜单中显示它们时,我得到了
I have a very strange problem with one of my db tables. I have various areas categorized in zones (Zone A, Zone B etc) and when I run a query to display them in a dropdown menu i get
- A区-K区
- A区-L区
- A区-M区
- A区-N区
- A区-O区
- A区-P区
- A区-A区
- A区-B区
- A区-C区
- A区-D区
- ...
- A区-G区
- B区-K区
- B区-L区
- B区-M区
- B区-N区
- B区-O区
- B区-P区
- B区-A区
- B区-B区
- B区-C区
- B区-D区
- Zone A - Area K
- Zone A - Area L
- Zone A - Area M
- Zone A - Area N
- Zone A - Area O
- Zone A - Area P
- Zone A - Area A
- Zone A - Area B
- Zone A - Area C
- Zone A - Area D
- ...
- Zone A - Area G
- Zone B - Area K
- Zone B - Area L
- Zone B - Area M
- Zone B - Area N
- Zone B - Area O
- Zone B - Area P
- Zone B - Area A
- Zone B - Area B
- Zone B - Area C
- Zone B - Area D
出于某些奇怪的原因,区域从K-> Z开始显示,然后从A开始.
For some strange reason the areas are being displayed from K->Z and then starts from A.
我的表的结构如下:CREATE TABLE区域(id int(11)NOT NULL AUTO_INCREMENT,区域varchar(20)DEFAULT NULL,区域varchar(100)NOT NULL,距离float(9,2)DEFAULT NULL,PRIMARY KEY(id))ENGINE = MyISAM DEFAULT CHARSET = utf8;
My table's structure is as follows: CREATE TABLE areas ( id int(11) NOT NULL AUTO_INCREMENT, zone varchar(20) DEFAULT NULL, area varchar(100) NOT NULL, distance float(9,2) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
我表中的数据是希腊文,我仅作了上面的示例,因此您可以理解并看到问题所在.要查看实际数据(希腊文),您可以访问 http://www.emanaviko.gr/lists/suburbs.php
The data in my table is in Greek, I made the above example only so you could understand and see the problem. To view the actual data (in Greek) you can visit http://www.emanaviko.gr/lists/suburbs.php
推荐答案
我已将您的数据导入到表中,它似乎与您得到的排序有所不同.您的默认排序规则是什么?我的是utf8_general_ci.
I've imported your data into a table and it seems to sort different from what you get. What is your default collation ? Mine is utf8_general_ci.
请注意,实际上,即使您是西式字母也不是西式字母.例如,您的K实际上是Unicode字符"GREEK CAPITAL LETTER KAPPA".
Note that even your western-looking letters are, in fact, not western letters. For instance, your K is in fact the unicode character "GREEK CAPITAL LETTER KAPPA".
mysql> show create table foo;
+-------+----------------------------------------------------------------------------------+
| Table | Create Table |
+-------+----------------------------------------------------------------------------------+
| foo | CREATE TABLE `foo` (
`z` text,
`a` text
) ENGINE=MyISAM DEFAULT CHARSET=utf8 |
+-------+----------------------------------------------------------------------------------+
mysql> select * from foo order by z,a collate utf8_general_ci;
+-------------+-------------------------------------------------+
| z | a |
+-------------+-------------------------------------------------+
| ΖΩΝΗ Α | Αγία Βαρβάρα |
| ΖΩΝΗ Α | Αγία Παρασκευή |
| ΖΩΝΗ Α | Αγιοι Ανάργυροι |
| ΖΩΝΗ Α | Αγιος Στέφανος |
| ΖΩΝΗ Α | Αιγάλεω |
| ΖΩΝΗ Α | Ανθούσα |
| ΖΩΝΗ Α | Ανοιξη |
| ΖΩΝΗ Α | Ανω Λιόσια |
| ΖΩΝΗ Α | Αχαρνές (Μενίδι) |
| ΖΩΝΗ Α | Βριλήσσια |
| ΖΩΝΗ Α | Γαλάτσι |
| ΖΩΝΗ Α | Γέρακας |
| ΖΩΝΗ Α | Γλυκά Νερά |
| ΖΩΝΗ Α | Διόνυσος |
| ΖΩΝΗ Α | Δροσιά |
| ΖΩΝΗ Α | Εκάλη |
| ΖΩΝΗ Α | Ζεφύρι |
| ΖΩΝΗ Α | Ηράκλειο |
| ΖΩΝΗ Α | Θρακομακεδόνες |
| ΖΩΝΗ Α | Ιλιον |
| ΖΩΝΗ Α | Κηφισιά |
| ΖΩΝΗ Α | Κρυονέρι |
| ΖΩΝΗ Α | Λυκόβρυση |
| ΖΩΝΗ Α | Μαρούσι |
| ΖΩΝΗ Α | Μελίσσια |
| ΖΩΝΗ Α | Νέα Ερυθραία |
| ΖΩΝΗ Α | Παλλήνη |
| ΖΩΝΗ Α | Παπάγου |
| ΖΩΝΗ Α | Πεντέλη |
| ΖΩΝΗ Α | Περιστέρι |
| ΖΩΝΗ Α | Πετρούπολη |
| ΖΩΝΗ Α | Πεύκη |
| ΖΩΝΗ Α | Ροδόπολη |
| ΖΩΝΗ Α | Σταμάτα |
| ΖΩΝΗ Α | Φιλοθέη |
| ΖΩΝΗ Α | Χαϊδάρι |
| ΖΩΝΗ Α | Χαλάνδρι |
| ΖΩΝΗ Α | Χαλκηδόνα |
| ΖΩΝΗ Α | Χολαργός |
| ΖΩΝΗ Α | Ψυχικό |
| ΖΩΝΗ Β | Αγία Σοφία |
| ΖΩΝΗ Β | Αγιος Βασίλειος |
| ΖΩΝΗ Β | Αγιος Δημήτριος(Μπραχάμι) |
| ΖΩΝΗ Β | Αλιμος |
| ΖΩΝΗ Β | Ανω Γλυφάδα |
| ΖΩΝΗ Β | Αργυρούπολη |
| ΖΩΝΗ Β | Βάρη |
| ΖΩΝΗ Β | Βάρκιζα |
| ΖΩΝΗ Β | Βούλα |
| ΖΩΝΗ Β | Βουλιαγμένη |
| ΖΩΝΗ Β | Βύρωνας |
| ΖΩΝΗ Β | Γλυφάδα |
| ΖΩΝΗ Β | Δάφνη |
| ΖΩΝΗ Β | Ελληνικό |
| ΖΩΝΗ Β | Ζωγράφου |
| ΖΩΝΗ Β | Ηλιούπολη |
| ΖΩΝΗ Β | Καβούρι |
| ΖΩΝΗ Β | Καισαριανή |
| ΖΩΝΗ Β | Καλλιθέα |
| ΖΩΝΗ Β | Καλλίπολη |
| ΖΩΝΗ Β | Καμίνια |
| ΖΩΝΗ Β | Καστέλα |
| ΖΩΝΗ Β | Νέα Σμύρνη |
| ΖΩΝΗ Β | Παλαιό Φάληρο |
| ΖΩΝΗ Β | Υμηττός |
+-------------+-------------------------------------------------+
65 rows in set (0.00 sec)
mysql> set names utf8;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from foo order by z,a collate utf8_general_ci;
+-------------+-------------------------------------------------+
| z | a |
+-------------+-------------------------------------------------+
| ΖΩΝΗ Α | Αγία Βαρβάρα |
| ΖΩΝΗ Α | Αγία Παρασκευή |
| ΖΩΝΗ Α | Αγιοι Ανάργυροι |
| ΖΩΝΗ Α | Αγιος Στέφανος |
| ΖΩΝΗ Α | Αιγάλεω |
| ΖΩΝΗ Α | Ανθούσα |
| ΖΩΝΗ Α | Ανοιξη |
| ΖΩΝΗ Α | Ανω Λιόσια |
| ΖΩΝΗ Α | Αχαρνές (Μενίδι) |
| ΖΩΝΗ Α | Βριλήσσια |
| ΖΩΝΗ Α | Γαλάτσι |
| ΖΩΝΗ Α | Γέρακας |
| ΖΩΝΗ Α | Γλυκά Νερά |
| ΖΩΝΗ Α | Διόνυσος |
| ΖΩΝΗ Α | Δροσιά |
| ΖΩΝΗ Α | Εκάλη |
| ΖΩΝΗ Α | Ζεφύρι |
| ΖΩΝΗ Α | Ηράκλειο |
| ΖΩΝΗ Α | Θρακομακεδόνες |
| ΖΩΝΗ Α | Ιλιον |
| ΖΩΝΗ Α | Κηφισιά |
| ΖΩΝΗ Α | Κρυονέρι |
| ΖΩΝΗ Α | Λυκόβρυση |
| ΖΩΝΗ Α | Μαρούσι |
| ΖΩΝΗ Α | Μελίσσια |
| ΖΩΝΗ Α | Νέα Ερυθραία |
| ΖΩΝΗ Α | Παλλήνη |
| ΖΩΝΗ Α | Παπάγου |
| ΖΩΝΗ Α | Πεντέλη |
| ΖΩΝΗ Α | Περιστέρι |
| ΖΩΝΗ Α | Πετρούπολη |
| ΖΩΝΗ Α | Πεύκη |
| ΖΩΝΗ Α | Ροδόπολη |
| ΖΩΝΗ Α | Σταμάτα |
| ΖΩΝΗ Α | Φιλοθέη |
| ΖΩΝΗ Α | Χαϊδάρι |
| ΖΩΝΗ Α | Χαλάνδρι |
| ΖΩΝΗ Α | Χαλκηδόνα |
| ΖΩΝΗ Α | Χολαργός |
| ΖΩΝΗ Α | Ψυχικό |
| ΖΩΝΗ Β | Αγία Σοφία |
| ΖΩΝΗ Β | Αγιος Βασίλειος |
| ΖΩΝΗ Β | Αγιος Δημήτριος(Μπραχάμι) |
| ΖΩΝΗ Β | Αλιμος |
| ΖΩΝΗ Β | Ανω Γλυφάδα |
| ΖΩΝΗ Β | Αργυρούπολη |
| ΖΩΝΗ Β | Βάρη |
| ΖΩΝΗ Β | Βάρκιζα |
| ΖΩΝΗ Β | Βούλα |
| ΖΩΝΗ Β | Βουλιαγμένη |
| ΖΩΝΗ Β | Βύρωνας |
| ΖΩΝΗ Β | Γλυφάδα |
| ΖΩΝΗ Β | Δάφνη |
| ΖΩΝΗ Β | Ελληνικό |
| ΖΩΝΗ Β | Ζωγράφου |
| ΖΩΝΗ Β | Ηλιούπολη |
| ΖΩΝΗ Β | Καβούρι |
| ΖΩΝΗ Β | Καισαριανή |
| ΖΩΝΗ Β | Καλλιθέα |
| ΖΩΝΗ Β | Καλλίπολη |
| ΖΩΝΗ Β | Καμίνια |
| ΖΩΝΗ Β | Καστέλα |
| ΖΩΝΗ Β | Νέα Σμύρνη |
| ΖΩΝΗ Β | Παλαιό Φάληρο |
| ΖΩΝΗ Β | Υμηττός |
+-------------+-------------------------------------------------+
更新:
好.我导入了您的转储文件.
OK. I imported your dump file.
您的问题是表格包含错误的数据.实际上是双重编码的utf8.
Your problem is that the tables contain the wrong data. It is in fact double-encoded utf8.
使用phpmyadmin查看表:您应该看到垃圾而不是文本.
Look into the tables using phpmyadmin : you should see garbage instead of text.
您的PHP代码中可能存在一个错误,您忘记发布"SET NAMES utf8"或mysql_set_charset("utf8").而且插入时您也遇到了同样的错误.
You probably have a bug in your PHP code, that you forgot to issue a "SET NAMES utf8" or a mysql_set_charset("utf8"). And you had the same bug when inserting.
因此,当您发出
INSERT 'Αγία Παρασκευή'
PHP将utf-8编码的数据发送到MySQL.但是MySQL认为它是latin1.因此,它将再次将其转换为utf8,并且您的表中包含垃圾.
PHP sends utf-8 encoded data to MySQL. But MySQL believes it is latin1. So, it converts it again to utf8, and your table contains garbage.
当您进行SELECT时,mysql会将utf8转换回latin1,但这实际上为您提供了最初发送的utf8,因此它可以正确显示在您的应用程序中.
When you SELECT, mysql converts utf8 back to latin1, but this actually gives you the utf8 you sent originally, so it displays correctly in your application.
但是表的内容是垃圾,并按垃圾顺序排序;)
But the contents of the tables are garbage, and sort in garbage order ;)
首先,您需要在代码中修复该错误.
First you need to fix that bug in your code.
然后,您需要导出这些表(提供的文件效果很好),将其删除,然后使用正确的字符集重新导入它们(在文件顶部添加一个SET NAMES utf8).
Then you need to export those tables (the file you gave works fine), drop them, and re-import them using the correct charset (add a SET NAMES utf8 at the top of the file).
更新2:
如果您想知道数据是否不是垃圾,有一些简单的技巧:
If you want to know if the data isn't garbage, there are simple tricks :
SELECT upper(yourcolumn) (or lower()...)
SELECT char_length(yourcolumn)
如果它有效(即,您获得了正确的大写或小写文本以及正确的字符长度,则表明数据是正确的,并且mysql能够理解.
If it works (ie, you get the right uppercase or lowercase text and the right length in characters, then it means the data is good and mysql understands it.
检查您的mysql连接是否正确配置的常见技巧是发出(在您的php代码中)此查询:
Common trick to check if your mysql connection is properly configured is to issue (in your php code) this query :
SELECT char_length('é'), octet_length('é'), upper('é')
+-------------------+--------------------+-------------+
| char_length('é') | octet_length('é') | upper('é') |
+-------------------+--------------------+-------------+
| 1 | 2 | É |
+-------------------+--------------------+-------------+
您当然可以
SHOW VARIABLES LIKE '%character%';
我使用phpmyadmin和mysql控制台.
I use phpmyadmin and the mysql console.
这篇关于PHP,MySQL中带有utf8数据的奇怪排序问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!