MySQL create table 语句包含每个 char、varchar 和文本列的冗余排序规则声明是否正常?
Is it normal for a MySQL create table statement to include redundant collation declarations for every char, varchar, and text column?
当 运行 SHOW CREATE TABLE `my_table`;
时,我注意到 COLLATE utf8mb4_unicode_ci
显示在每个 char
、varchar
和 text
列中table。这似乎有点多余,因为排序规则已经在 create 语句的 table_option 部分中声明。
mysql> SHOW CREATE TABLE `my_table`;
| Table | Create Table
| my_table | CREATE TABLE `my_table` (
...
`char_col_1` char(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`varchar_col_1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`varchar_col_2` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`varchar_col_3` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`text_col_1` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
...
) ENGINE=InnoDB AUTO_INCREMENT=1816178 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
此行为在 MySQL 5.7 和 MySQL 8.0 中都很明显,因此在其他版本中也很可能存在。
此行为是否正常并接受table,或者它是否是 table、数据库或 MySQL 实例配置错误的症状?
另一方面,由于可以为任何特定列单独设置排序规则,也许最好明确显示每个列的排序规则以避免任何歧义或假设,即使在列排序规则匹配的情况下table?
的排序规则
是的,CHARACTER SET
和 COLLATION
在 table 定义和列定义中相同是多余的。
具有明确的列定义意味着任何人更改 CHARACTER SET
或 COLLATION
的 table 定义,该列将保持不变。
您所触及的只是冰山一角。
- 我认为 table 上的设置只是未定义字符集或整理的列的默认值。
- 同上
ALTER TABLE ADD COLUMN
-- 将从 table 默认值继承。
- 我认为列设置已放入
information_schema.COLUMNS
table 并且不会随着 ALTER TABLE .. MODIFY COLUMN ..
而改变
同样,table charset 和 collation 继承自 database 定义,将被冻结为 table 已定义。
关于默认值:
- 旧的默认字符集是
latin1
- 当前默认为
utf8mb4
;这在未来不太可能改变。
- 每个归类只适用于一个字符集,字符集名称是归类名称的开头。
- 每个字符集只有一个 "default" 排序规则:
latin1_swedish_ci
、utf8_unicode_ci
、utf8mb4_0900_ai_ci
等
- 默认排序规则(对于给定的字符集)很少(如果有的话)改变过。也许唯一的变化是 utf8mb4 在 5.7 和 8.0 之间??
(我实验的越多,我对这一切就越不确定。)
最佳做法:始终为每个字符串列显式设置 CHARSET
和 COLLATE
。
次要考虑因素:
- 如果可用,对大多数字符串 (
VARCHAR
/ TEXT
) 使用 utf8mb4
。
- 使用最新可用的排序规则(Unicode 不断改进它);目前
utf8mb4_0900_ai_ci
.
- 使用
ascii
用于显然只有 ascii 的东西——国家代码、postal_code、十六进制等。大多数情况下这些可以使用 CHAR(..)
- 使用
ascii_general_ci
或ascii_bin
,取决于是否需要大小写折叠。
当 运行 SHOW CREATE TABLE `my_table`;
时,我注意到 COLLATE utf8mb4_unicode_ci
显示在每个 char
、varchar
和 text
列中table。这似乎有点多余,因为排序规则已经在 create 语句的 table_option 部分中声明。
mysql> SHOW CREATE TABLE `my_table`;
| Table | Create Table
| my_table | CREATE TABLE `my_table` (
...
`char_col_1` char(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`varchar_col_1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`varchar_col_2` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`varchar_col_3` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`text_col_1` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
...
) ENGINE=InnoDB AUTO_INCREMENT=1816178 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
此行为在 MySQL 5.7 和 MySQL 8.0 中都很明显,因此在其他版本中也很可能存在。
此行为是否正常并接受table,或者它是否是 table、数据库或 MySQL 实例配置错误的症状?
另一方面,由于可以为任何特定列单独设置排序规则,也许最好明确显示每个列的排序规则以避免任何歧义或假设,即使在列排序规则匹配的情况下table?
的排序规则是的,CHARACTER SET
和 COLLATION
在 table 定义和列定义中相同是多余的。
具有明确的列定义意味着任何人更改 CHARACTER SET
或 COLLATION
的 table 定义,该列将保持不变。
您所触及的只是冰山一角。
- 我认为 table 上的设置只是未定义字符集或整理的列的默认值。
- 同上
ALTER TABLE ADD COLUMN
-- 将从 table 默认值继承。 - 我认为列设置已放入
information_schema.COLUMNS
table 并且不会随着ALTER TABLE .. MODIFY COLUMN ..
而改变
同样,table charset 和 collation 继承自 database 定义,将被冻结为 table 已定义。
关于默认值:
- 旧的默认字符集是
latin1
- 当前默认为
utf8mb4
;这在未来不太可能改变。 - 每个归类只适用于一个字符集,字符集名称是归类名称的开头。
- 每个字符集只有一个 "default" 排序规则:
latin1_swedish_ci
、utf8_unicode_ci
、utf8mb4_0900_ai_ci
等 - 默认排序规则(对于给定的字符集)很少(如果有的话)改变过。也许唯一的变化是 utf8mb4 在 5.7 和 8.0 之间??
(我实验的越多,我对这一切就越不确定。)
最佳做法:始终为每个字符串列显式设置 CHARSET
和 COLLATE
。
次要考虑因素:
- 如果可用,对大多数字符串 (
VARCHAR
/TEXT
) 使用utf8mb4
。 - 使用最新可用的排序规则(Unicode 不断改进它);目前
utf8mb4_0900_ai_ci
. - 使用
ascii
用于显然只有 ascii 的东西——国家代码、postal_code、十六进制等。大多数情况下这些可以使用CHAR(..)
- 使用
ascii_general_ci
或ascii_bin
,取决于是否需要大小写折叠。