我想知道,对于您不能100%确定将要输入的内容的普通网站,MySQL中是否有“最佳”排序选择?我知道所有的编码应该是相同的,比如MySQL、Apache、HTML和PHP中的任何内容。
在过去,我将PHP设置为以“UTF-8”输出,但这与MySQL中的排序规则匹配?我认为它是UTF-8之一,但我以前使用过utf8_unicode_ci、utf8_general_ci和utf8_bin。
我想知道,对于您不能100%确定将要输入的内容的普通网站,MySQL中是否有“最佳”排序选择?我知道所有的编码应该是相同的,比如MySQL、Apache、HTML和PHP中的任何内容。
在过去,我将PHP设置为以“UTF-8”输出,但这与MySQL中的排序规则匹配?我认为它是UTF-8之一,但我以前使用过utf8_unicode_ci、utf8_general_ci和utf8_bin。
当前回答
排序规则影响数据的排序方式以及字符串之间的比较方式。这意味着您应该使用大多数用户期望的排序规则。
charset unicode文档中的示例:
utf8_general_ci也令人满意德语和法语,除了“ß”等于“s”,而不是“ss”。如果您可以接受应用程序,则应使用utf8_general_ci,因为它更快。否则,请使用utf8_unicode_ci,因为它更准确。
所以,这取决于您的预期用户群以及您需要正确排序的程度。对于英语用户群,utf8_general_ci应该足够了,对于其他语言,如瑞典语,已经创建了特殊的排序规则。
其他回答
排序规则影响数据的排序方式以及字符串之间的比较方式。这意味着您应该使用大多数用户期望的排序规则。
charset unicode文档中的示例:
utf8_general_ci也令人满意德语和法语,除了“ß”等于“s”,而不是“ss”。如果您可以接受应用程序,则应使用utf8_general_ci,因为它更快。否则,请使用utf8_unicode_ci,因为它更准确。
所以,这取决于您的预期用户群以及您需要正确排序的程度。对于英语用户群,utf8_general_ci应该足够了,对于其他语言,如瑞典语,已经创建了特殊的排序规则。
实际上,您可能希望使用utf8_unicode_ci或utf8_general_ci。
utf8_general_ci通过去掉所有重音符号进行排序,并将其排序为ASCIIutf8_unicode_ci使用unicode排序顺序,因此可以在更多语言中正确排序
然而,如果您只是使用它来存储英文文本,那么它们应该不会不同。
非常非常注意使用utf8_general_ci时可能出现的问题。
当使用utf8_general_ci排序规则时,MySQL不会区分select语句中的某些字符。这可能会导致非常严重的错误,尤其是涉及用户名的错误。根据使用数据库表的实现,此问题可能允许恶意用户创建与管理员帐户匹配的用户名。
这个问题至少在5.x早期版本中会暴露出来——我不确定这种行为后来是否发生了变化。
我不是DBA,但为了避免这个问题,我总是使用utf8 bin,而不是不区分大小写的bin。
下面的脚本通过示例描述了问题。
-- first, create a sandbox to play in
CREATE DATABASE `sandbox`;
use `sandbox`;
-- next, make sure that your client connection is of the same
-- character/collate type as the one we're going to test next:
charset utf8 collate utf8_general_ci
-- now, create the table and fill it with values
CREATE TABLE `test` (`key` VARCHAR(16), `value` VARCHAR(16) )
CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO `test` VALUES ('Key ONE', 'value'), ('Key TWO', 'valúe');
-- (verify)
SELECT * FROM `test`;
-- now, expose the problem/bug:
SELECT * FROM test WHERE `value` = 'value';
--
-- Note that we get BOTH keys here! MySQLs UTF8 collates that are
-- case insensitive (ending with _ci) do not distinguish between
-- both values!
--
-- collate 'utf8_bin' doesn't have this problem, as I'll show next:
--
-- first, reset the client connection charset/collate type
charset utf8 collate utf8_bin
-- next, convert the values that we've previously inserted in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;
-- now, re-check for the bug
SELECT * FROM test WHERE `value` = 'value';
--
-- Note that we get just one key now, as you'd expect.
--
-- This problem appears to be specific to utf8. Next, I'll try to
-- do the same with the 'latin1' charset:
--
-- first, reset the client connection charset/collate type
charset latin1 collate latin1_general_ci
-- next, convert the values that we've previously inserted
-- in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET latin1 COLLATE latin1_general_ci;
-- now, re-check for the bug
SELECT * FROM test WHERE `value` = 'value';
--
-- Again, only one key is returned (expected). This shows
-- that the problem with utf8/utf8_generic_ci isn't present
-- in latin1/latin1_general_ci
--
-- To complete the example, I'll check with the binary collate
-- of latin1 as well:
-- first, reset the client connection charset/collate type
charset latin1 collate latin1_bin
-- next, convert the values that we've previously inserted in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET latin1 COLLATE latin1_bin;
-- now, re-check for the bug
SELECT * FROM test WHERE `value` = 'value';
--
-- Again, only one key is returned (expected).
--
-- Finally, I'll re-introduce the problem in the exact same
-- way (for any sceptics out there):
-- first, reset the client connection charset/collate type
charset utf8 collate utf8_generic_ci
-- next, convert the values that we've previously inserted in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
-- now, re-check for the problem/bug
SELECT * FROM test WHERE `value` = 'value';
--
-- Two keys.
--
DROP DATABASE sandbox;
主要区别是排序精度(比较语言中的字符时)和性能。唯一特殊的是utf8_bin,它用于比较二进制格式的字符。
utf8_generalci比utf8_unicodeci稍快,但不太准确(用于排序)。特定语言utf8编码(如utf8_swedish_ci)包含额外的语言规则,这些规则使这些语言的排序最准确。大多数时候我使用utf8_unicode_ci(我更喜欢精确性而不是小的性能改进),除非我有充分的理由更喜欢特定的语言。
您可以在MySQL手册上阅读有关特定unicode字符集的更多信息-http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html
我发现这些整理图表很有用。http://collation-charts.org/mysql60/.但我不确定哪个是使用的utf8_general_ci。
例如,这里是utf8_swedish_ci的图表。它显示了它解释为相同的字符。http://collation-charts.org/mysql60/mysql604.utf8_swedish_ci.html