MySQL8 中文参考(四十四)

原文:docs.oracle.com/javase/tutorial/reallybigindex.html

12.10.8 二进制字符集

原文:dev.mysql.com/doc/refman/8.0/en/charset-binary-set.html

binary字符集是二进制字符串的字符集,即字节序列。binary字符集有一个排序规则,也称为binary。比较和排序基于数字字节值,而不是数字字符代码值(对于多字节字符,它们与数字字节值不同)。有关binary字符集的binary排序规则与非二进制字符集的_bin排序规则之间的区别,请参见第 12.8.5 节,“与 _bin 排序规则相比的 binary 排序规则”。

对于binary字符集,大小写和重音等效的概念不适用:

  • 对于存储为二进制字符串的单字节字符,字符和字节边界相同,因此在比较中大小写和重音差异很重要。也就是说,binary排序是区分大小写和重音的。

    mysql> SET NAMES 'binary';
    mysql> SELECT CHARSET('abc'), COLLATION('abc');
    +----------------+------------------+
    | CHARSET('abc') | COLLATION('abc') |
    +----------------+------------------+
    | binary         | binary           |
    +----------------+------------------+
    mysql> SELECT 'abc' = 'ABC', 'a' = 'ä';
    +---------------+------------+
    | 'abc' = 'ABC' | 'a' = 'ä'  |
    +---------------+------------+
    |             0 |          0 |
    +---------------+------------+
    
  • 对于存储为二进制字符串的多字节字符,字符和字节边界不同。字符边界丢失,因此依赖于它们的比较是没有意义的。

要对二进制字符串执行大小写转换,首先将其转换为使用适合字符串中存储的数据的字符集的非二进制字符串:

mysql> SET @str = BINARY 'New York';
mysql> SELECT LOWER(@str), LOWER(CONVERT(@str USING utf8mb4));
+-------------+------------------------------------+
| LOWER(@str) | LOWER(CONVERT(@str USING utf8mb4)) |
+-------------+------------------------------------+
| New York    | new york                           |
+-------------+------------------------------------+

要将字符串表达式转换为二进制字符串,以下构造是等效的:

BINARY *expr*
CAST(*expr* AS BINARY)
CONVERT(*expr* USING BINARY)

如果一个值是字符字符串文字,则可以使用_binary介绍符将其指定为二进制字符串。例如:

_binary 'a'

_binary介绍符也适用于十六进制文字和位值文字,但是不必要;这些文字默认为二进制字符串。

有关介绍符的更多信息,请参见第 12.3.8 节,“字符集介绍符”。

注意

mysql客户端中,二进制字符串使用十六进制表示,具体取决于--binary-as-hex的值。有关该选项的更多信息,请参见第 6.5.1 节,“mysql — MySQL 命令行客户端”。

12.11 字符集限制

原文:dev.mysql.com/doc/refman/8.0/en/charset-restrictions.html

  • 标识符存储在mysql数据库表(userdb等)中,使用utf8mb3,但标识符只能包含基本多文种平面(BMP)中的字符。标识符中不允许使用补充字符。

  • ucs2utf16utf16leutf32字符集有以下限制:

    • 不能将它们中的任何一个用作客户端字符集。参见不允许的客户端字符集。

    • 目前无法使用LOAD DATA加载使用这些字符集的数据文件。

    • 不能在使用任何这些字符集的列上创建FULLTEXT索引。但是,您可以在没有索引的情况下对该列执行IN BOOLEAN MODE搜索。

  • REGEXPRLIKE运算符以字节方式工作,因此它们不是多字节安全的,可能会在多字节字符集下产生意外结果。此外,这些运算符通过它们的字节值比较字符,即使给定的排序将它们视为相等,重音字符也可能不会被视为相等。

12.12 设置错误消息语言

原文:dev.mysql.com/doc/refman/8.0/en/error-message-language.html

默认情况下,mysqld会以英语显示错误消息,但可以改为显示其他几种语言:捷克语、丹麦语、荷兰语、爱沙尼亚语、法语、德语、希腊语、匈牙利语、意大利语、日语、韩语、挪威语、挪威-纽约语、波兰语、葡萄牙语、罗马尼亚语、俄语、斯洛伐克语、西班牙语或瑞典语。这适用于服务器写入错误日志并发送给客户端的消息。

要选择服务器写入错误消息的语言,请按照本节中的说明操作。有关更改错误消息的字符集(而不是语言)的信息,请参阅第 12.6 节,“错误消息字符集”。有关配置错误日志的一般信息,请参阅第 7.4.2 节,“错误日志”。

服务器根据以下规则搜索错误消息文件:

  • 它会在从两个系统变量值lc_messages_dirlc_messages构造的目录中查找文件,后者转换为语言名���。假设您使用以下命令启动服务器:

    mysqld --lc_messages_dir=/usr/share/mysql --lc_messages=fr_FR
    

    在这种情况下,mysqld将区域fr_FR映射到语言french,并在/usr/share/mysql/french目录中查找错误文件。

    默认情况下,语言文件位于 MySQL 基目录下的share/mysql/*LANGUAGE*目录中。

  • 如果无法在刚刚描述的构造目录中找到消息文件,则服务器将忽略lc_messages值,并仅使用lc_messages_dir值作为查找位置。

  • 如果服务器找不到配置的消息文件,它会向错误日志写入一条消息以指示问题,并默认使用内置的英语消息。

lc_messages_dir系统变量只能在服务器启动时设置,并且在运行时只有一个全局只读值。lc_messages可以在服务器启动时设置,并且具有可以在运行时修改的全局和会话值。因此,服务器在运行时可以更改错误消息语言,每个客户端可以通过将其会话lc_messages值设置为所需的区域名称来拥有自己的错误消息语言。例如,如果服务器使用fr_FR区域设置来显示错误消息,客户端可以执行以下语句以接收英语错误消息:

SET lc_messages = 'en_US';

12.13 添加字符集

原文:dev.mysql.com/doc/refman/8.0/en/adding-character-set.html

12.13.1 字符定义数组

12.13.2 复杂字符集的字符串排序支持

12.13.3 复杂字符集的多字节字符支持

本节讨论了向 MySQL 添加字符集的过程。正确的过程取决于字符集是简单还是复杂:

  • 如果字符集不需要用于排序的特殊字符串排序例程,也不需要多字节字符支持,则它是简单的。

  • 如果字符集需要这些功能中的任何一个,它就是复杂的。

例如,greekswe7是简单字符集,而big5czech是复杂字符集。

要使用以下说明,您必须具有 MySQL 源代码分发。在说明中,*MYSET*代表您想要添加的字符集的名称。

  1. sql/share/charsets/Index.xml文件的*MYSET*添加一个<charset>元素。使用文件中现有内容作为添加新内容的指南。latin1 <charset>元素的部分列表如下:

    <charset name="latin1">
      <family>Western</family>
      <description>cp1252 West European</description>
      ...
      <collation name="latin1_swedish_ci" id="8" order="Finnish, Swedish">
        <flag>primary</flag>
        <flag>compiled</flag>
      </collation>
      <collation name="latin1_danish_ci" id="15" order="Danish"/>
      ...
      <collation name="latin1_bin" id="47" order="Binary">
        <flag>binary</flag>
        <flag>compiled</flag>
      </collation>
      ...
    </charset>
    

    <charset>元素必须列出字符集的所有排序规则。这些排序规则必须至少包括一个二进制排序规则和一个默认(主要)排序规则。默认排序规则通常使用general_ci(通用,不区分大小写)后缀命名。二进制排序规则可能是默认排序规则,但通常它们是不同的。默认排序规则应该有一个primary标志。二进制排序规则应该有一个binary标志。

    您必须为每个排序规则分配一个唯一的 ID 号。ID 范围从 1024 到 2047 保留用于用户定义的排序规则。要找到当前使用的排序规则 ID 的最大值,请使用此查询:

    SELECT MAX(ID) FROM INFORMATION_SCHEMA.COLLATIONS;
    
  2. 此步骤取决于您是添加简单字符集还是复杂字符集。简单字符集只需要一个配置文件,而复杂字符集需要定义排序函数、多字节函数或两者的 C 源文件。

    对于简单字符集,创建一个配置文件,*MYSET*.xml,描述字符集属性。将此文件创建在sql/share/charsets目录中。您可以使用latin1.xml的副本作为此文件的基础。文件的语法非常简单:

    • 注释写作普通的 XML 注释(<!-- *text* -->)。

    • <map>数组元素内的单词由任意数量的空格分隔。

    • <map>数组元素内的每个单词必须是十六进制格式的数字。

    • <ctype>元素的<map>数组元素有 257 个单词。之后的其他<map>数组元素有 256 个单词。参见第 12.13.1 节,“字符定义数组”。

    • 对于Index.xml中字符集的<charset>元素中列出的每个排序,*MYSET*.xml必须包含定义字符排序的<collation>元素。

    对于复杂字符集,创建一个描述字符集属性并定义支持操作所需的支持例程的 C 源文件:

    • strings目录中创建文件ctype-*MYSET*.c。查看现有的ctype-*.c文件(如ctype-big5.c)以了解需要定义的内容。您的文件中的数组必须具有类似ctype_*MYSET*to_lower_*MYSET*等的名称。这些对应于简单字符集的数组。参见第 12.13.1 节,“字符定义数组”。

    • 对于Index.xml中字符集的<charset>元素中列出的每个<collation>元素,ctype-*MYSET*.c文件必须提供排序的实现。

    • 如果字符集需要字符串排序函数,请参见第 12.13.2 节,“复杂字符集的字符串排序支持”。

    • 如果字符集需要多字节字符支持,请参见第 12.13.3 节,“复杂字符集的多字节字符支持”。

  3. 修改配置信息。使用现有的配置信息作为为*MYSYS添加信息的指南。此示例假定字符集具有默认和二进制排序,但如果MYSET*具有其他排序,则需要更多行。

    1. 编辑mysys/charset-def.c,并“注册”新字符集的排序。

      将这些行添加到“声明”部分:

      #ifdef HAVE_CHARSET_*MYSET*
      extern CHARSET_INFO my_charset_*MYSET*_general_ci;
      extern CHARSET_INFO my_charset_*MYSET*_bin;
      #endif
      

      将这些行添加到“注册”部分:

      #ifdef HAVE_CHARSET_*MYSET*
        add_compiled_collation(&my_charset_*MYSET*_general_ci);
        add_compiled_collation(&my_charset_*MYSET*_bin);
      #endif
      
    2. 如果字符集使用ctype-*MYSET*.c,编辑strings/CMakeLists.txt并将ctype-*MYSET*.c添加到STRINGS_SOURCES变量的定义中。

    3. 编辑cmake/character_sets.cmake

      1. 将*MYSET*添加到CHARSETS_AVAILABLE的值中,按字母顺序排列。

      2. 将*MYSET*按字母顺序添加到CHARSETS_COMPLEX的值中。即使对于简单字符集也需要这样做,以便CMake可以识别-DDEFAULT_CHARSET=*MYSET*

  4. 重新配置、重新编译并测试。

12.13.1 字符定义数组

dev.mysql.com/doc/refman/8.0/en/character-arrays.html

每个简单字符集都有一个配置文件,位于 sql/share/charsets 目录中。 对于名为 MYSYS 的字符集,文件名为 *MYSET*.xml。 它使用 <map> 数组元素列出字符集属性。 <map> 元素出现在这些元素内部:

  • <ctype> 为每个字符定义属性。

  • <lower><upper> 列出小写和大写字符。

  • <unicode> 将 8 位字符值映射到 Unicode 值。

  • <collation> 元素指示用于比较和排序的字符排序,每个排序一个元素。 二进制排序不需要 <map> 元素,因为字符代码本身提供排序。

对于在 strings 目录中的 ctype-*MYSET*.c 文件中实现的复杂字符集,有相应的数组:ctype_*MYSET*[]to_lower_*MYSET*[] 等等。 并非每个复杂字符集都有所有数组。 有关示例,请参见现有的 ctype-*.c 文件。 有关更多信息,请参见 strings 目录中的 CHARSET_INFO.txt 文件。

大多数数组按字符值索引,并具有 256 个元素。 <ctype> 数组按字符值 + 1 索引,并具有 257 个元素。 这是处理 EOF 的传统约定。

<ctype> 数组元素是位值。 每个元素描述字符集中单个字符的属性。 每个属性与位掩码关联,如 include/m_ctype.h 中定义的:

#define _MY_U   01 /* Upper case */
#define _MY_L   02 /* Lower case */
#define _MY_NMR 04 /* Numeral (digit) */
#define _MY_SPC 010 /* Spacing character */
#define _MY_PNT 020 /* Punctuation */
#define _MY_CTR 040 /* Control character */
#define _MY_B   0100 /* Blank */
#define _MY_X   0200 /* heXadecimal digit */

给定字符的 <ctype> 值应该是描述该字符的适用位掩码值的并集。 例如,'A' 是大写字符(_MY_U)以及十六进制数字(_MY_X),因此其 ctype 值应该定义如下:

ctype['A'+1] = _MY_U | _MY_X = 01 | 0200 = 0201

m_ctype.h 中的位掩码值是八进制值,但在 *MYSET*.xml 中的 <ctype> 数组的元素应该以十六进制值编写。

<lower><upper> 数组保存与字符集中每个成员对应的小写和大写字符。 例如:

lower['A'] should contain 'a'
upper['a'] should contain 'A'

每个 <collation> 数组指示字符应如何排序以进行比较和排序。 MySQL 根据此信息的值对字符进行排序。 在某些情况下,这与 <upper> 数组相同,这意味着排序不区分大小写。 对于更复杂的排序规则(用于复杂字符集),请参阅 12.13.2 “复杂字符集的字符串排序支持” 中有关字符串排序的讨论。

12.13.2 复杂字符集的字符串排序支持

原文:dev.mysql.com/doc/refman/8.0/en/string-collating.html

对于一个名为*MYSET*的简单字符集,排序规则在*MYSET*.xml配置文件中使用<collation>元素内的<map>数组元素指定。如果你的语言的排序规则过于复杂,无法用简单的数组处理,你必须在strings目录中的ctype-*MYSET*.c源文件中定义字符串排序函数。

现有的字符集提供了最好的文档和示例,展示了这些函数是如何实现的。查看strings目录中的ctype-*.c文件,比如big5czechgbksjistis160字符集的文件。查看MY_COLLATION_HANDLER结构体,了解它们是如何使用的。另请参阅strings目录中的CHARSET_INFO.txt文件获取更多信息。

12.13.3 复杂字符集的多字节字符支持

原文:dev.mysql.com/doc/refman/8.0/en/multibyte-characters.html

如果您想要为一个名为*MYSET*的新字符集添加多字节字符支持,您必须在strings目录中的ctype-*MYSET*.c源文件中使用多字节字符函数。

现有的字符集提供了最佳的文档和示例,展示了这些函数是如何实现的。查看strings目录中的ctype-*.c文件,例如euc_krgb2312gbksjisujis字符集的文件。查看MY_CHARSET_HANDLER结构以了解它们的使用方式。另请参阅strings目录中的CHARSET_INFO.txt文件获取更多信息。

12.14 向字符集添加排序

原文:dev.mysql.com/doc/refman/8.0/en/adding-collation.html

12.14.1 排序实现类型

12.14.2 选择排序 ID

12.14.3 向 8 位字符集添加简单排序

12.14.4 向 Unicode 字符集添加 UCA 排序

警告

用户定义的排序已被弃用;您应该期望在将来的 MySQL 版本中删除对它们的支持。从 MySQL 8.0.33 开始,服务器对任何 SQL 语句中使用 COLLATE *user_defined_collation* 都会发出警告;当服务器以 --collation-server 设置为用户定义排序的名称启动时,也会发出警告。

排序是一组定义如何比较和排序字符串的规则。MySQL 中的每个排序都属于单个字符集。每个字符集至少有一个排序,大多数有两个或更多排序。

字符串排序是基于权重的。字符集中的每个字符都映射到一个权重。具有相同权重的字符比较相等,具有不同权重的字符根据其权重的相对大小进行比较。

WEIGHT_STRING() 函数可用于查看字符串中字符的权重。它返回的表示权重的值是一个二进制字符串,因此方便使用 HEX(WEIGHT_STRING(*str*)) 以可打印形式显示权重。以下示例显示,如果是非二进制不区分大小写字符串,则对于 'AaBb' 中的字母,权重不会有区别,但如果是二进制字符串,则会有区别:

mysql> SELECT HEX(WEIGHT_STRING('AaBb' COLLATE latin1_swedish_ci));
+------------------------------------------------------+
| HEX(WEIGHT_STRING('AaBb' COLLATE latin1_swedish_ci)) |
+------------------------------------------------------+
| 41414242                                             |
+------------------------------------------------------+
mysql> SELECT HEX(WEIGHT_STRING(BINARY 'AaBb'));
+-----------------------------------+
| HEX(WEIGHT_STRING(BINARY 'AaBb')) |
+-----------------------------------+
| 41614262                          |
+-----------------------------------+

MySQL 支持多种排序实现,如 第 12.14.1 节“排序实现类型” 中讨论的。其中一些可以在不重新编译 MySQL 的情况下添加:

  • 8 位字符集的简单排序。

  • 基于 UCA 的 Unicode 字符集排序。

  • 二进制 (*xxx*_bin) 排序。

以下部分描述如何向现有字符集添加前两种类型的用户定义排序。所有现有字符集已经有一个二进制排序,因此这里不需要描述如何添加一个。

警告

不支持重新定义内置排序,并可能导致意外的服务器行为。

添加新用户定义排序的步骤摘要:

  1. 选择一个排序 ID。

  2. 添加配置信息,命名排序规则并描述字符排序规则。

  3. 重新启动服务器。

  4. 确保服务器识别排序。

此处的说明仅涵盖可以在不重新编译 MySQL 的情况下添加的用户定义排序规则。要添加需要重新编译的排序规则(通过在 C 源文件中使用函数实现),请使用第 12.13 节的说明,“添加字符集”。但是,不要添加完整字符集所需的所有信息,只需修改现有字符集的适当文件。也就是说,根据当前字符集的排序规则已有的内容,为新的排序规则添加数据结构、函数和配置信息。

注意

如果您修改现有的用户定义排序规则,可能会影响使用该排序规则的列索引的行排序。在这种情况下,重新构建任何此类索引以避免问题,如查询结果不正确。请参见第 3.14 节,“重建或修复表或索引”。

附加资源

12.14.1 整理实现类型

原文:dev.mysql.com/doc/refman/8.0/en/charset-collation-implementations.html

MySQL 实现了几种类型的整理:

8 位字符集的简单整理

这种整理使用一个包含 256 个权重的数组来实现,定义了从字符代码到权重的一对一映射。latin1_swedish_ci是一个例子。它是一个不区分大小写的整理,因此字符的大写和小写版本具有相同的权重,它们比较相等。

mysql> SET NAMES 'latin1' COLLATE 'latin1_swedish_ci';
Query OK, 0 rows affected (0.01 sec)

mysql> SELECT HEX(WEIGHT_STRING('a')), HEX(WEIGHT_STRING('A'));
+-------------------------+-------------------------+
| HEX(WEIGHT_STRING('a')) | HEX(WEIGHT_STRING('A')) |
+-------------------------+-------------------------+
| 41                      | 41                      |
+-------------------------+-------------------------+
1 row in set (0.01 sec)

mysql> SELECT 'a' = 'A';
+-----------+
| 'a' = 'A' |
+-----------+
|         1 |
+-----------+
1 row in set (0.12 sec)

有关实现说明,请参见第 12.14.3 节,“向 8 位字符集添加简单整理”。

8 位字符集的复杂整理

这种整理使用 C 源文件中的函数来定义如何对字符进行排序,如第 12.13 节,“添加字符集”中所述。

非 Unicode 多字节字符集的整理

对于这种类型的整理,8 位(单字节)和多字节字符的处理方式不同。对于 8 位字符,字符代码以不区分大小写的方式映射到权重。(例如,单字节字符'a''A'都具有权重0x41。)对于多字节字符,字符代码和权重之间有两种关系:

  • 权重等于字符代码。sjis_japanese_ci是这种整理的一个例子。多字节字符'ぢ'的字符代码为0x82C0,权重也是0x82C0

    mysql> CREATE TABLE t1
           (c1 VARCHAR(2) CHARACTER SET sjis COLLATE sjis_japanese_ci);
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> INSERT INTO t1 VALUES ('a'),('A'),(0x82C0);
    Query OK, 3 rows affected (0.00 sec)
    Records: 3  Duplicates: 0  Warnings: 0
    
    mysql> SELECT c1, HEX(c1), HEX(WEIGHT_STRING(c1)) FROM t1;
    +------+---------+------------------------+
    | c1   | HEX(c1) | HEX(WEIGHT_STRING(c1)) |
    +------+---------+------------------------+
    | a    | 61      | 41                     |
    | A    | 41      | 41                     |
    || 82C0    | 82C0                   |
    +------+---------+------------------------+
    3 rows in set (0.00 sec)
    
  • 字符代码一对一映射到权重,但代码不一定等于权重。gbk_chinese_ci是这种整理的一个例子。多字节字符'膰'的字符代码为0x81B0,但权重为0xC286

    mysql> CREATE TABLE t1
           (c1 VARCHAR(2) CHARACTER SET gbk COLLATE gbk_chinese_ci);
    Query OK, 0 rows affected (0.33 sec)
    
    mysql> INSERT INTO t1 VALUES ('a'),('A'),(0x81B0);
    Query OK, 3 rows affected (0.00 sec)
    Records: 3  Duplicates: 0  Warnings: 0
    
    mysql> SELECT c1, HEX(c1), HEX(WEIGHT_STRING(c1)) FROM t1;
    +------+---------+------------------------+
    | c1   | HEX(c1) | HEX(WEIGHT_STRING(c1)) |
    +------+---------+------------------------+
    | a    | 61      | 41                     |
    | A    | 41      | 41                     |
    || 81B0    | C286                   |
    +------+---------+------------------------+
    3 rows in set (0.00 sec)
    

有关实现说明,请参见第 12.13 节,“添加字符集”。

Unicode 多字节字符集的整理

这些整理中有一些基于 Unicode 整理算法(UCA),而其他一些则不是。

非 UCA 整理将字符代码一对一映射到权重。在 MySQL 中,这种整理不区分大小写,也不区分重音。utf8mb4_general_ci是一个例子:'a''A''À''á'每个具有不同的字符代码,但都具有权重0x0041,并且比较相等。

mysql> SET NAMES 'utf8mb4' COLLATE 'utf8mb4_general_ci';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE t1
       (c1 CHAR(1) CHARACTER SET UTF8MB4 COLLATE utf8mb4_general_ci);
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO t1 VALUES ('a'),('A'),('À'),('á');
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT c1, HEX(c1), HEX(WEIGHT_STRING(c1)) FROM t1;
+------+---------+------------------------+
| c1   | HEX(c1) | HEX(WEIGHT_STRING(c1)) |
+------+---------+------------------------+
| a    | 61      | 0041                   |
| A    | 41      | 0041                   |
| À    | C380    | 0041                   |
| á    | C3A1    | 0041                   |
+------+---------+------------------------+
4 rows in set (0.00 sec)

MySQL 中基于 UCA 的整理具有以下特性:

  • 如果一个字符有权重,每个权重使用 2 个字节(16 位)。

  • 一个字符可能有零个权重(或空权重)。在这种情况下,该字符是可忽略的。例如:"U+0000 NULL"没有权重,是可忽略的。

  • 一个字符可能有一个权重。例如:'a'的权重为0x0E33

    mysql> SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci';
    Query OK, 0 rows affected (0.05 sec)
    
    mysql> SELECT HEX('a'), HEX(WEIGHT_STRING('a'));
    +----------+-------------------------+
    | HEX('a') | HEX(WEIGHT_STRING('a')) |
    +----------+-------------------------+
    | 61       | 0E33                    |
    +----------+-------------------------+
    1 row in set (0.02 sec)
    
  • 一个字符可能有多个权重。这是一个扩展。例如:德语字母'ß'(SZ 连字,或 SHARP S)的权重为0x0FEA0FEA

    mysql> SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci';
    Query OK, 0 rows affected (0.11 sec)
    
    mysql> SELECT HEX('ß'), HEX(WEIGHT_STRING('ß'));
    +-----------+--------------------------+
    | HEX('ß')  | HEX(WEIGHT_STRING('ß'))  |
    +-----------+--------------------------+
    | C39F      | 0FEA0FEA                 |
    +-----------+--------------------------+
    1 row in set (0.00 sec)
    
  • 多个字符可能有一个权重。这是一个收缩。例如:'ch'是捷克语中的一个字母,权重为0x0EE2

    mysql> SET NAMES 'utf8mb4' COLLATE 'utf8mb4_czech_ci';
    Query OK, 0 rows affected (0.09 sec)
    
    mysql> SELECT HEX('ch'), HEX(WEIGHT_STRING('ch'));
    +-----------+--------------------------+
    | HEX('ch') | HEX(WEIGHT_STRING('ch')) |
    +-----------+--------------------------+
    | 6368      | 0EE2                     |
    +-----------+--------------------------+
    1 row in set (0.00 sec)
    

也可能存在多字符对多权重的映射(这是扩展与收缩),但 MySQL 不支持。

对于非 UCA 排序的实现说明,请参见第 12.13 节,“添加字符集”。对于 UCA 排序,请参见第 12.14.4 节,“向 Unicode 字符集添加 UCA 排序”。

杂项排序

还有一些排序不属于前述任何类别。

12.14.2 选择排序规则 ID

原文:dev.mysql.com/doc/refman/8.0/en/adding-collation-choosing-id.html

每个排序规则必须有一个唯一的 ID。要添加排序规则,必须选择一个当前未使用的 ID 值。MySQL 支持两字节的排序规则 ID。ID 范围从 1024 到 2047 保留给用户定义的排序规则。

你选择的排序规则 ID 出现在以下情境中:

  • 信息模式 COLLATIONS 表的 ID 列。

  • SHOW COLLATION 输出的 Id 列。

  • MYSQL_FIELD C API 数据结构的 charsetnr 成员。

  • mysql_get_character_set_info() C API 函数返回的 MY_CHARSET_INFO 数据结构的 number 成员。

要确定当前使用的最大 ID,请执行以下语句:

mysql> SELECT MAX(ID) FROM INFORMATION_SCHEMA.COLLATIONS;
+---------+
| MAX(ID) |
+---------+
|     247 |
+---------+

要显示所有当前使用的 ID 列表,请执行此语句:

mysql> SELECT ID FROM INFORMATION_SCHEMA.COLLATIONS ORDER BY ID;
+-----+
| ID  |
+-----+
|   1 |
|   2 |
| ... |
|  52 |
|  53 |
|  57 |
|  58 |
| ... |
|  98 |
|  99 |
| 128 |
| 129 |
| ... |
| 247 |
+-----+

警告

在升级之前,应保存更改的配置文件。如果在原地升级,该过程将替换修改过的文件。

12.14.3 向 8 位字符集添加简单排序规则

原文:dev.mysql.com/doc/refman/8.0/en/adding-collation-simple-8bit.html

本节描述了如何通过在 MySQL 的Index.xml文件中编写与<charset>字符集描述相关联的<collation>元素来为 8 位字符集添加简单排序规则的过程。这里描述的过程不需要重新编译 MySQL。示例将一个名为latin1_test_ci的排序规则添加到latin1字符集中。

  1. 选择一个排序规则 ID,如第 12.14.2 节“选择排序规则 ID”所示。以下步骤使用 ID 为 1024。

  2. 修改Index.xmllatin1.xml配置文件。这些文件位于由character_sets_dir系统变量命名的目录中。您可以按照以下方式检查变量值,尽管在您的系统上路径名可能不同:

    mysql> SHOW VARIABLES LIKE 'character_sets_dir';
    +--------------------+-----------------------------------------+
    | Variable_name      | Value                                   |
    +--------------------+-----------------------------------------+
    | character_sets_dir | /user/local/mysql/share/mysql/charsets/ |
    +--------------------+-----------------------------------------+
    
  3. 为排序规则选择一个名称,并在Index.xml文件中列出。找到正在添加排序规则的字符集的<charset>元素,并添加一个<collation>元素,指示排序规则名称和 ID,以将名称与 ID 关联起来。例如:

    <charset name="latin1">
      ...
      <collation name="latin1_test_ci" id="1024"/>
      ...
    </charset>
    
  4. latin1.xml配置文件中,添加一个命名排序规则的<collation>元素,并包含一个<map>元素,为字符代码 0 到 255 定义一个字符代码到权重映射表。<map>元素中的每个值必须是十六进制格式的数字。

    <collation name="latin1_test_ci">
    <map>
     00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
     10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
     20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
     30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
     40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
     50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
     60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
     50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
     80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
     90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
     A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
     B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
     41 41 41 41 5B 5D 5B 43 45 45 45 45 49 49 49 49
     44 4E 4F 4F 4F 4F 5C D7 5C 55 55 55 59 59 DE DF
     41 41 41 41 5B 5D 5B 43 45 45 45 45 49 49 49 49
     44 4E 4F 4F 4F 4F 5C F7 5C 55 55 55 59 59 DE FF
    </map>
    </collation>
    
  5. 重新启动服务器,并使用此语句验证排序规则是否存在:

    mysql> SHOW COLLATION WHERE Collation = 'latin1_test_ci';
    +----------------+---------+------+---------+----------+---------+
    | Collation      | Charset | Id   | Default | Compiled | Sortlen |
    +----------------+---------+------+---------+----------+---------+
    | latin1_test_ci | latin1  | 1024 |         |          |       1 |
    +----------------+---------+------+---------+----------+---------+
    

12.14.4 向 Unicode 字符集添加 UCA 排序

原文:dev.mysql.com/doc/refman/8.0/en/adding-collation-unicode-uca.html

12.14.4.1 使用 LDML 语法定义 UCA 排序

12.14.4.2 MySQL 支持的 LDML 语法

12.14.4.3 在 Index.xml 解析期间的诊断

本节描述了如何通过在 MySQL 的 Index.xml 文件中的 <charset> 字符集描述中编写 <collation> 元素来添加 Unicode 字符集的 UCA 排序。这里描述的过程不需要重新编译 MySQL。它使用了 Locale Data Markup Language (LDML) 规范的一个子集,可在 www.unicode.org/reports/tr35/ 上找到。使用这种方法,您无需定义整个排序。相反,您从现有的“基本”排序开始,并描述新排序与基本排序的不同之处。以下表列出了可以定义 UCA 排序的 Unicode 字符集的基本排序。无法为 utf16le 创建用户定义的 UCA 排序;没有 utf16le_unicode_ci 排序可作为此类排序的基础。

表 12.4 可用于用户定义 UCA 排序的 MySQL 字符集

字符集基本排序
utf8mb4utf8mb4_unicode_ci
ucs2ucs2_unicode_ci
utf16utf16_unicode_ci
utf32utf32_unicode_ci

以下部分展示了如何添加使用 LDML 语法定义的排序,并提供了 MySQL 支持的 LDML 规则摘要。

原文:dev.mysql.com/doc/refman/8.0/en/ldml-collation-example.html

12.14.4.1 使用 LDML 语法定义 UCA 整理

要为 Unicode 字符集添加 UCA 整理而无需重新编译 MySQL,请使用以下过程。如果您不熟悉用于描述整理排序特性的 LDML 规则,请参阅第 12.14.4.2 节,“MySQL 支持的 LDML 语法”。

该示例向utf8mb4字符集添加了一个名为utf8mb4_phone_ci的整理。该整理设计用于涉及用户发布其姓名和电话号码的 Web 应用程序的场景。电话号码可以以非常不同的格式给出:

+7-12345-67
+7-12-345-67
+7 12 345 67
+7 (12) 345 67
+71234567

处理这些类型值时引发的问题是,不同的允许格式使得搜索特定电话号码变得非常困难。解决方案是定义一个重新排序标点字符的新整理,使它们可忽略。

  1. 选择一个整理 ID,如第 12.14.2 节,“选择整理 ID”所示。以下步骤使用 ID 为 1029。

  2. 修改Index.xml配置文件。该文件位于由character_sets_dir系统变量命名的目录中。您可以按照以下方式检查变量值,尽管路径名可能在您的系统上有所不同:

    mysql> SHOW VARIABLES LIKE 'character_sets_dir';
    +--------------------+-----------------------------------------+
    | Variable_name      | Value                                   |
    +--------------------+-----------------------------------------+
    | character_sets_dir | /user/local/mysql/share/mysql/charsets/ |
    +--------------------+-----------------------------------------+
    
  3. 为整理选择一个名称,并在Index.xml文件中列出它。此外,您需要提供整理排序规则。找到正在添加整理的字符集的<charset>元素,并添加一个指示整理名称和 ID 的<collation>元素,以将名称与 ID 关联起来。在<collation>元素内,提供包含排序规则的<rules>元素:

    <charset name="utf8mb4">
      ...
      <collation name="utf8mb4_phone_ci" id="1029">
        <rules>
          <reset>\u0000</reset>
          <i>\u0020</i> <!-- space -->
          <i>\u0028</i> <!-- left parenthesis -->
          <i>\u0029</i> <!-- right parenthesis -->
          <i>\u002B</i> <!-- plus -->
          <i>\u002D</i> <!-- hyphen -->
        </rules>
      </collation>
      ...
    </charset>
    
  4. 如果您希望为其他 Unicode 字符集添加类似的整理,添加其他<collation>元素。例如,要定义ucs2_phone_ci,请向<charset name="ucs2">元素添加一个<collation>元素。请记住,每个整理必须有其自己的唯一 ID。

  5. 重新启动服务器并使用此语句验证整理是否存在:

    mysql> SHOW COLLATION WHERE Collation = 'utf8mb4_phone_ci';
    +------------------+---------+------+---------+----------+---------+
    | Collation        | Charset | Id   | Default | Compiled | Sortlen |
    +------------------+---------+------+---------+----------+---------+
    | utf8mb4_phone_ci | utf8mb4 | 1029 |         |          |       8 |
    +------------------+---------+------+---------+----------+---------+
    

现在测试整理,确保它具有所需的属性。

创建一个包含一些使用新整理的示例电话号码的表:

mysql> CREATE TABLE phonebook (
         name VARCHAR(64),
         phone VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_phone_ci
       );
Query OK, 0 rows affected (0.09 sec)

mysql> INSERT INTO phonebook VALUES ('Svoj','+7 912 800 80 02');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO phonebook VALUES ('Hf','+7 (912) 800 80 04');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO phonebook VALUES ('Bar','+7-912-800-80-01');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO phonebook VALUES ('Ramil','(7912) 800 80 03');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO phonebook VALUES ('Sanja','+380 (912) 8008005');
Query OK, 1 row affected (0.00 sec)

运行一些查询,查看忽略的标点字符是否实际上被忽略以进行比较和排序:

mysql> SELECT * FROM phonebook ORDER BY phone;
+-------+--------------------+
| name  | phone              |
+-------+--------------------+
| Sanja | +380 (912) 8008005 |
| Bar   | +7-912-800-80-01   |
| Svoj  | +7 912 800 80 02   |
| Ramil | (7912) 800 80 03   |
| Hf    | +7 (912) 800 80 04 |
+-------+--------------------+
5 rows in set (0.00 sec)

mysql> SELECT * FROM phonebook WHERE phone='+7(912)800-80-01';
+------+------------------+
| name | phone            |
+------+------------------+
| Bar  | +7-912-800-80-01 |
+------+------------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM phonebook WHERE phone='79128008001';
+------+------------------+
| name | phone            |
+------+------------------+
| Bar  | +7-912-800-80-01 |
+------+------------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM phonebook WHERE phone='7 9 1 2 8 0 0 8 0 0 1';
+------+------------------+
| name | phone            |
+------+------------------+
| Bar  | +7-912-800-80-01 |
+------+------------------+
1 row in set (0.00 sec)

原文:dev.mysql.com/doc/refman/8.0/en/ldml-rules.html

12.14.4.2 MySQL 支持的 LDML 语法

本节描述了 MySQL 识别的 LDML 语法。这是 LDML 规范中描述的语法的子集,可在www.unicode.org/reports/tr35/找到,应该查阅以获取更多信息。MySQL 识别了足够大的语法子集,因此在许多情况下,可以从 Unicode 通用区域数据存储库下载排序定义,并将相关部分(即在<rules></rules>标记之间的部分)粘贴到 MySQL 的Index.xml文件中。这里描述的规则都受支持,只是字符排序仅在主要级别发生。指定在次要或更高排序级别上存在差异的规则被识别(因此可以包含在排序定义中),但在主要级别被视为相等。

当 MySQL 服务器在解析Index.xml文件时发现问题时,会生成诊断信息。请参阅第 12.14.4.3 节,“解析 Index.xml 时的诊断”。

字符表示

在 LDML 规则中命名的字符可以直接写出,也可以用\u*nnnn*格式,其中*nnnn*是十六进制 Unicode 代码点值。例如,Aá可以直接写出,也可以写为\u0041\u00E1。在十六进制值中,字母AF不区分大小写;\u00E1\u00e1是等效的。对于 UCA 4.0.0 排序,只能对基本多文种平面中的字符使用十六进制表示法,而不能对超出0000FFFF的 BMP 范围的字符使用。对于 UCA 5.2.0 排序,可以对任何字符使用十六进制表示法。

Index.xml文件本身应使用 UTF-8 编码编写。

语法规则

LDML 具有重置规则和移位规则,用于指定字符排序。排序规则被给定为一组以建立锚点的重置规则开头的规则,然后是指示字符相对于锚点如何排序的移位规则。

  • <reset>规则本身不指定任何排序。相反,它“重置”后续移位规则,使它们相对于给定字符进行排序。以下任一规则都会将后续移位规则重置为相对于字母'A'进行排序:

    <reset>A</reset>
    
    <reset>\u0041</reset>
    
  • <p><s><t>移位规则定义了一个字符与另一个字符的主要、次要和三级差异:

    • 使用主要差异来区分不同的字母。

    • 使用次要差异来区分重音变体。

    • 使用三级差异来区分大小写变体。

    以下任一规则指定了字符'G'的主要移位规则:

    <p>G</p>
    
    <p>\u0047</p>
    
  • <i>移位规则表示一个字符与另一个字符排序相同。以下规则使'b''a'排序相同:

    <reset>a</reset>
    <i>b</i>
    
  • 缩写的移位语法使用一对标签指定多个移位规则。以下表格显示了缩写语法规则与等效的非缩写规则之间的对应关系。

    表 12.5 缩写的移位语法

    缩写语法非缩写语法
    <pc>xyz</pc><p>x</p><p>y</p><p>z</p>
    <sc>xyz</sc><s>x</s><s>y</s><s>z</s>
    <tc>xyz</tc><t>x</t><t>y</t><t>z</t>
    <ic>xyz</ic><i>x</i><i>y</i><i>z</i>
  • 扩展是一个重置规则,为多字符序列建立锚点。MySQL 支持 2 到 6 个字符长的扩展。以下规则将'z'放在主级别比三个字符序列'abc'更大:

    <reset>abc</reset>
    <p>z</p>
    
  • 缩写是将多字符序列排序的移位规则。MySQL 支持 2 到 6 个字符长的缩写。以下规则将三个字符序列'xyz'放在主级别比'a'更大:

    <reset>a</reset>
    <p>xyz</p>
    
  • 长扩展和长缩写可以一起使用。这些规则将三个字符序列'xyz'放在主级别比三个字符序列'abc'更大:

    <reset>abc</reset>
    <p>xyz</p>
    
  • 正常的扩展语法使用<x>加上<extend>元素来指定一个扩展。以下规则将字符'k'放在二级别比序列'ch'更大。也就是说,'k'的行为就像它扩展到'c'后跟着'h'的字符一样:

    <reset>c</reset>
    <x><s>k</s><extend>h</extend></x>
    

    这种语法允许长序列。这些规则将序列'ccs'放在三级别比序列'cscs'更大:

    <reset>cs</reset>
    <x><t>ccs</t><extend>cs</extend></x>
    

    LDML 规范将正常扩展语法描述为“棘手”。详细信息请参阅该规范。

  • 先前的上下文语法使用<x>加上<context>元素来指定字符前的上下文影响其排序方式。以下规则将'-'放在二级比'a'更大,但仅当'-'出现在'b'之后时:

    <reset>a</reset>
    <x><context>b</context><s>-</s></x>
    
  • 先前的上下文语法可以包括<extend>元素。这些规则将'def'放在主级别比'aghi'更大,但仅当'def'出现在'abc'之后时:

    <reset>a</reset>
    <x><context>abc</context><p>def</p><extend>ghi</extend></x>
    
  • 重置规则允许before属性。通常,在重置规则之后的移位规则指示在重置字符之后排序的字符。在具有before属性的重置规则之后的移位规则指示在重置字符之前排序的字符。以下规则将字符'b'立即放在主级别的'a'之前:

    <reset before="primary">a</reset>
    <p>b</p>
    

    允许的before属性值通过名称或等效的数值指定排序级别:

    <reset before="primary">
    <reset before="1">
    
    <reset before="secondary">
    <reset before="2">
    
    <reset before="tertiary">
    <reset before="3">
    
  • 重置规则可以命名逻辑重置位置而不是文字字符:

    <first_tertiary_ignorable/>
    <last_tertiary_ignorable/>
    <first_secondary_ignorable/>
    <last_secondary_ignorable/>
    <first_primary_ignorable/>
    <last_primary_ignorable/>
    <first_variable/>
    <last_variable/>
    <first_non_ignorable/>
    <last_non_ignorable/>
    <first_trailing/>
    <last_trailing/>
    

    这些规则将'z'放在主级别比具有默认 Unicode 排序元素表(DUCET)条目且不是 CJK 的不可忽略字符更大:

    <reset><last_non_ignorable/></reset>
    <p>z</p>
    

    逻辑位置在下表中显示了代码点。

    表 12.6 逻辑重置位置代码点

    逻辑位置Unicode 4.0.0 代码点Unicode 5.2.0 代码点
    <first_non_ignorable/>U+02D0U+02D0
    <last_non_ignorable/>U+A48CU+1342E
    <first_primary_ignorable/>U+0332U+0332
    <last_primary_ignorable/>U+20EAU+101FD
    <first_secondary_ignorable/>U+0000U+0000
    <last_secondary_ignorable/>U+FE73U+FE73
    <first_tertiary_ignorable/>U+0000U+0000
    <last_tertiary_ignorable/>U+FE73U+FE73
    <first_trailing/>U+0000U+0000
    <last_trailing/>U+0000U+0000
    <first_variable/>U+0009U+0009
    <last_variable/>U+2183U+1D371
    逻辑位置Unicode 4.0.0 代码点Unicode 5.2.0 代码点
  • <collation>元素允许shift-after-method属性,该属性影响移位规则的字符权重计算。该属性有以下允许的值:

    • simple: 计算字符权重,就像没有before属性的重置规则一样。如果未给出属性,则这是默认值。

    • expand: 使用扩展来处理重置规则后的偏移。

    假设'0''1'的权重分别为0E290E2A,我们想在'0''1'之间放置所有基本拉丁字母:

    <reset>0</reset>
    <pc>abcdefghijklmnopqrstuvwxyz</pc>
    

    对于简单的移位模式,权重计算如下:

    'a' has weight 0E29+1
    'b' has weight 0E29+2
    'c' has weight 0E29+3
    ...
    

    然而,在'0''1'之间没有足够的空位来放置 26 个字符。结果是数字和字母混合在一起。

    要解决这个问题,使用shift-after-method="expand"。然后权重计算如下:

    'a' has weight [0E29][233D+1]
    'b' has weight [0E29][233D+2]
    'c' has weight [0E29][233D+3]
    ...
    

    233D 是字符0xA48C的 UCA 4.0.0 权重,它是最后一个非可忽略字符(排序中最大的字符,不包括 CJK)。UCA 5.2.0 类似,但使用3ACA,对于字符0x1342E

MySQL 特定的 LDML 扩展

LDML 规则的扩展允许<collation>元素在<collation>标签中包含一个可选的version属性,以指示排序所基于的 UCA 版本。如果省略version属性,则其默认值为4.0.0。例如,此规范指示基于 UCA 5.2.0 的排序:

<collation id="*nnn*" name="utf8mb4_*xxx*_ci" version="5.2.0">
...
</collation>

原文:dev.mysql.com/doc/refman/8.0/en/collation-diagnostics.html

12.14.4.3 Index.xml 解析期间的诊断

MySQL 服务器在解析Index.xml文件时发现问题时会生成诊断信息:

  • 未知标记会被写入错误日志。例如,如果排序规则定义包含<aaa>标记,则会产生以下消息:

    [Warning] Buffered warning: Unknown LDML tag:
    'charsets/charset/collation/rules/aaa'
    
  • 如果排序规则初始化不可能,服务器会报告“未知排序规则”错误,并生成解释问题的警告,就像前面的例子一样。在其他情况下,如果排序规则描述通常正确但包含一些未知标记,排序规则会被初始化并可供使用。未知部分会被忽略,但错误日志中会生成警告。

  • 排序规则存在问题会生成警告,客户端可以使用SHOW WARNINGS显示这些警告。假设重置规则包含一个长度超过 6 个字符的扩展:

    <reset>abcdefghi</reset>
    <i>x</i>
    

    尝试使用排序规则会产生警告:

    mysql> SELECT _utf8mb4'test' COLLATE utf8mb4_test_ci;
    ERROR 1273 (HY000): Unknown collation: 'utf8mb4_test_ci'
    mysql> SHOW WARNINGS;
    +---------+------+----------------------------------------+
    | Level   | Code | Message                                |
    +---------+------+----------------------------------------+
    | Error   | 1273 | Unknown collation: 'utf8mb4_test_ci'   |
    | Warning | 1273 | Expansion is too long at 'abcdefghi=x' |
    +---------+------+----------------------------------------+
    

12.15 字符集配置

原文:dev.mysql.com/doc/refman/8.0/en/charset-configuration.html

MySQL 服务器具有编译默认字符集和排序规则。要更改这些默认值,请在启动服务器时使用--character-set-server--collation-server选项。请参阅第 7.1.7 节,“服务器命令选项”。排序规则必须是默认字符集的合法排序规则。要确定每个字符集可用的排序规则,请使用SHOW COLLATION语句或查询INFORMATION_SCHEMA COLLATIONS表。

如果您尝试使用未编译到二进制文件中的字符集,可能会遇到以下问题:

  • 如果您的程序使用不正确的路径来确定字符集存储的位置(通常是 MySQL 安装目录下的share/mysql/charsetsshare/charsets目录),可以通过在运行程序时使用--character-sets-dir选项来解决。例如,要指定一个目录供 MySQL 客户端程序使用,请在您的选项文件的[client]组中列出它。这里给出的示例显示了在 Unix 或 Windows 中分别设置可能是什么样子的:

    [client]
    character-sets-dir=/usr/local/mysql/share/mysql/charsets
    
    [client]
    character-sets-dir="C:/Program Files/MySQL/MySQL Server 8.0/share/charsets"
    
  • 如果字符集是一个无法动态加载的复杂字符集,您必须重新编译程序以支持该字符集。

    对于 Unicode 字符集,您可以使用 LDML 表示法定义排序规则,而无需重新编译。请参阅第 12.14.4 节,“向 Unicode 字符集添加 UCA 排序规则”。

  • 如果字符集是动态字符集,但您没有配置文件,您应该从新的 MySQL 发行版中安装字符集的配置文件。

  • 如果您的字符集索引文件(Index.xml)不包含字符集的名称,您的程序将显示错误消息:

    Character set '*charset_name*' is not a compiled character set and is not
    specified in the '/usr/share/mysql/charsets/Index.xml' file
    

    要解决这个问题,您应该获取一个新的索引文件或手动将任何缺失的字符集名称添加到当前文件中。

您可以强制客户端程序使用特定的字符集,如下所示:

[client]
default-character-set=*charset_name*

这通常是不必要的。然而,当character_set_systemcharacter_set_servercharacter_set_client不同时,并且您手动输入字符(作为数据库对象标识符、列值或两者),这些字符可能会在客户端输出中显示不正确,或者输出本身可能格式不正确。在这种情况下,使用--default-character-set=*system_character_set*启动 mysql 客户端——即,将客户端字符集设置为与系统字符集匹配——应该可以解决问题。

12.16 MySQL 服务器区域设置支持

原文:dev.mysql.com/doc/refman/8.0/en/locale-support.html

lc_time_names 系统变量指示的区域控制用于显示日期和月份名称和缩写的语言。 此变量影响 DATE_FORMAT()DAYNAME()MONTHNAME() 函数的输出。

lc_time_names 不会影响 STR_TO_DATE()GET_FORMAT() 函数。

lc_time_names 的值不会影响 FORMAT() 的结果,但此函数接受一个可选的第三个参数,该参数允许指定用于结果数字的小数点、千位分隔符和分隔符之间分组的区域设置。 可接受的区域值与 lc_time_names 系统变量的合法值相同。

区域名称由 IANA 列出的语言和地区子标签组成(www.iana.org/assignments/language-subtag-registry),例如 'ja_JP''pt_BR'。 默认值是 'en_US',不受系统区域设置影响,但您可以在服务器启动时设置该值,或者在运行时设置 GLOBAL 值(如果您有足够的权限设置全局系统变量);参见 7.1.9.1 系统变量权限。 任何客户端都可以检查 lc_time_names 的值或设置其 SESSION 值以影响自己连接的区域设置。

mysql> SET NAMES 'utf8mb4';
Query OK, 0 rows affected (0.09 sec)

mysql> SELECT @@lc_time_names;
+-----------------+
| @@lc_time_names |
+-----------------+
| en_US           |
+-----------------+
1 row in set (0.00 sec)

mysql> SELECT DAYNAME('2020-01-01'), MONTHNAME('2020-01-01');
+-----------------------+-------------------------+
| DAYNAME('2020-01-01') | MONTHNAME('2020-01-01') |
+-----------------------+-------------------------+
| Wednesday             | January                 |
+-----------------------+-------------------------+
1 row in set (0.00 sec)

mysql> SELECT DATE_FORMAT('2020-01-01','%W %a %M %b');
+-----------------------------------------+
| DATE_FORMAT('2020-01-01','%W %a %M %b') |
+-----------------------------------------+
| Wednesday Wed January Jan               |
+-----------------------------------------+
1 row in set (0.00 sec)

mysql> SET lc_time_names = 'es_MX';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @@lc_time_names;
+-----------------+
| @@lc_time_names |
+-----------------+
| es_MX           |
+-----------------+
1 row in set (0.00 sec)

mysql> SELECT DAYNAME('2020-01-01'), MONTHNAME('2020-01-01');
+-----------------------+-------------------------+
| DAYNAME('2020-01-01') | MONTHNAME('2020-01-01') |
+-----------------------+-------------------------+
| miércoles             | enero                   |
+-----------------------+-------------------------+
1 row in set (0.00 sec)

mysql> SELECT DATE_FORMAT('2020-01-01','%W %a %M %b');
+-----------------------------------------+
| DATE_FORMAT('2020-01-01','%W %a %M %b') |
+-----------------------------------------+
| miércoles mié enero ene                 |
+-----------------------------------------+
1 row in set (0.00 sec)

受影响函数的每个日期或月份名称都从 utf8mb4 转换为由 character_set_connection 系统变量指示的字符集。

lc_time_names 可设置为以下任一区域值。 MySQL 支持的区域集合可能与操作系统支持的不同。

区域值含义
ar_AE阿拉伯语 - 阿拉伯联合酋长国
ar_BH阿拉伯语 - 巴林
ar_DZ阿拉伯语 - 阿尔及利亚
ar_EG阿拉伯语 - 埃及
ar_IN阿拉伯语 - 印度
ar_IQ阿拉伯语 - 伊拉克
ar_JO阿拉伯语 - 约旦
ar_KW阿拉伯语 - 科威特
ar_LB阿拉伯语 - 黎巴嫩
ar_LY阿拉伯语 - 利比亚
ar_MA阿拉伯语 - 摩洛哥
ar_OM阿拉伯语 - 阿曼
ar_QA阿拉伯语 - 卡塔尔
ar_SA阿拉伯语 - 沙特阿拉伯
ar_SD阿拉伯语 - 苏丹
ar_SY阿拉伯语 - 叙利亚
ar_TN阿拉伯语 - 突尼斯
ar_YE阿拉伯语 - 也门
be_BY白俄罗斯语 - 白俄罗斯
bg_BG保加利亚语 - 保加利亚
ca_ES加泰罗尼亚语 - 西班牙
cs_CZ捷克语 - 捷克共和国
da_DK丹麦语 - 丹麦
de_AT德语 - 奥地利
de_BE德语 - 比利时
de_CH德语 - 瑞士
de_DE德语 - 德国
de_LU德语 - 卢森堡
el_GR希腊语 - 希腊
en_AU英语 - 澳大利亚
en_CA英语 - 加拿大
en_GB英语 - 英国
en_IN英语 - 印度
en_NZ英语 - 新西兰
en_PH英语 - 菲律宾
en_US英语 - 美国
en_ZA英语 - 南非
en_ZW英语 - 津巴布韦
es_AR西班牙语 - 阿根廷
es_BO西班牙语 - 玻利维亚
es_CL西班牙语 - 智利
es_CO西班牙语 - 哥伦比亚
es_CR西班牙语 - 哥斯达黎加
es_DO西班牙语 - 多米尼加共和国
es_EC西班牙语 - 厄瓜多尔
es_ES西班牙语 - 西班牙
es_GT西班牙语 - 危地马拉
es_HN西班牙语 - 洪都拉斯
es_MX西班牙语 - 墨西哥
es_NI西班牙语 - 尼加拉瓜
es_PA西班牙语 - 巴拿马
es_PE西班牙语 - 秘鲁
es_PR西班牙语 - 波多黎各
es_PY西班牙语 - 巴拉圭
es_SV西班牙语 - 萨尔瓦多
es_US西班牙语 - 美国
es_UY西班牙语 - 乌拉圭
es_VE西班牙语 - 委内瑞拉
et_EE爱沙尼亚语 - 爱沙尼亚
eu_ES巴斯克语 - 西班牙
fi_FI芬兰语 - 芬兰
fo_FO法罗语 - 法罗群岛
fr_BE法语 - 比利时
fr_CA法语 - 加拿大
fr_CH法语 - 瑞士
fr_FR法语 - 法国
fr_LU法语 - 卢森堡
gl_ES加利西亚语 - 西班牙
gu_IN古吉拉特语 - 印度
he_IL希伯来语 - 以色列
hi_IN印地语 - 印度
hr_HR克罗地亚语 - 克罗地亚
hu_HU匈牙利语 - 匈牙利
id_ID印尼语 - 印度尼西亚
is_IS冰岛语 - 冰岛
it_CH意大利语 - 瑞士
it_IT意大利语 - 意大利
ja_JP日语 - 日本
ko_KR韩语 - 韩国
lt_LT立陶宛语 - 立陶宛
lv_LV拉脱维亚语 - 拉脱维亚
mk_MK马其顿语 - 北马其顿
mn_MN蒙古语 - 蒙古
ms_MY马来语 - 马来西亚
nb_NO挪威语(书面) - 挪威
nl_BE荷兰语 - ��利时
nl_NL荷兰语 - 荷兰
no_NO挪威语 - 挪威
pl_PL波兰语 - 波兰
pt_BR葡萄牙语 - 巴西
pt_PT葡萄牙语 - 葡萄牙
rm_CH罗曼什语 - 瑞士
ro_RO罗马尼亚语 - 罗马尼亚
ru_RU俄语 - 俄罗斯
ru_UA俄语 - 乌克兰
sk_SK斯洛伐克语 - 斯洛伐克
sl_SI斯洛文尼亚语 - 斯洛文尼亚
sq_AL阿尔巴尼亚语 - 阿尔巴尼亚
sr_RS塞尔维亚语 - 塞尔维亚
sv_FI瑞典语 - 芬兰
sv_SE瑞典语 - 瑞典
ta_IN泰米尔语 - 印度
te_IN泰卢固语 - 印度
th_TH泰语 - 泰国
tr_TR土耳其语 - 土耳其
uk_UA乌克兰语 - 乌克兰
ur_PK乌尔都语 - 巴基斯坦
vi_VN越南语 - 越南
zh_CN中文 - 中国
zh_HK中文 - 香港
zh_TW中文 - 台湾
Locale Value意义

第十三章 数据类型

原文:dev.mysql.com/doc/refman/8.0/en/data-types.html

目录

13.1 数值数据类型

13.1.1 数值数据类型语法

13.1.2 整数类型(精确值)- INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT

13.1.3 定点类型(精确值)- DECIMAL, NUMERIC

13.1.4 浮点类型(近似值)- FLOAT, DOUBLE

13.1.5 位值类型 - BIT

13.1.6 数值类型属性

13.1.7 超出范围和溢出处理

13.2 日期和时间数��类型

13.2.1 日期和时间数据类型语法

13.2.2 DATE, DATETIME 和 TIMESTAMP 类型

13.2.3 TIME 类型

13.2.4 YEAR 类型

13.2.5 TIMESTAMP 和 DATETIME 的自动初始化和更新

13.2.6 时间值中的小数秒

13.2.7 MySQL 使用哪种日历?

13.2.8 日期和时间类型之间的转换

13.2.9 日期中的两位年份

13.3 字符串数据类型

13.3.1 字符串数据类型语法

13.3.2 CHAR 和 VARCHAR 类型

13.3.3 BINARY 和 VARBINARY 类型

13.3.4 BLOB 和 TEXT 类型

13.3.5 ENUM 类型

13.3.6 SET 类型

13.4 空间数据类型

13.4.1 空间数据类型

13.4.2 OpenGIS 几何模型

13.4.3 支持的空间数据格式

13.4.4 几何形状的正确性和有效性

13.4.5 空间参考系统支持

13.4.6 创建空间列

13.4.7 填充空间列

13.4.8 获取空间数据

13.4.9 优化空间分析

13.4.10 创建空间索引

13.4.11 使用空间索引

13.5 JSON 数据类型

13.6 数据类型默认值

13.7 数据类型存储要求

13.8 选择列的正确类型

13.9 使用其他数据库引擎的数据类型

MySQL 支持几个类别的 SQL 数据类型:数值类型、日期和时间类型、字符串(字符和字节)类型、空间类型和 JSON 数据类型。本章提供了每个类别中类型属性的概述和更详细的描述,以及数据类型存储需求的摘要。初始概述故意简短。请参阅更详细的描述,了解有关特定数据类型的其他信息,例如您可以指定值的允许格式。

数据类型描述使用以下约定:

  • 对于整数类型,M 表示最大显示宽度。对于浮点和定点类型,M 是可以存储的总位数(精度)。对于字符串类型,M 是最大长度。M 的最大允许值取决于数据类型。

  • D 适用于浮点和定点类型,表示小数点后的位数(精度)。最大可能值为 30,但不应大于 *M*−2。

  • fsp 适用于 TIMEDATETIMETIMESTAMP 类型,表示小数秒精度;即,小数秒部分的小数点后的位数。如果给定 fsp 值,则必须在范围 0 到 6 之间。值为 0 表示没有小数部分。如果省略,则默认精度为 0。(这与标准 SQL 默认值 6 不同,以与之前的 MySQL 版本兼容。)

  • 方括号([])表示类型定义的可选部分。

13.1 数值数据类型

原文:dev.mysql.com/doc/refman/8.0/en/numeric-types.html

13.1.1 数值数据类型语法

13.1.2 整数类型(精确值) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT

13.1.3 定点类型(精确值) - DECIMAL, NUMERIC

13.1.4 浮点类型(近似值) - FLOAT, DOUBLE

13.1.5 位值类型 - BIT

13.1.6 数值类型属性

13.1.7 超出范围和溢出处理

MySQL 支持所有标准 SQL 数值数据类型。这些类型包括精确数值数据类型(INTEGER, SMALLINT, DECIMALNUMERIC),以及近似数值数据类型(FLOAT, REALDOUBLE PRECISION)。关键字INTINTEGER的同义词,关键字DECFIXEDDECIMAL的同义词。MySQL 将DOUBLE视为DOUBLE PRECISION的同义词(非标准扩展)。MySQL 还将REAL视为DOUBLE PRECISION的同义词(非标准变体),除非启用了REAL_AS_FLOAT SQL 模式。

BIT数据类型存储位值,并支持MyISAMMEMORYInnoDBNDB表。

有关 MySQL 如何处理超出范围值分配给列和在表达式评估期间的溢出的信息,请参阅第 13.1.7 节,“超出范围和溢出处理”。

有关数值数据类型的存储要求的信息,请参阅第 13.7 节,“数据类型存储要求”。

对于操作数值的函数描述,请参阅第 14.6 节,“数值函数和运算符”。对于数值操作数计算结果使用的数据类型取决于操作数的类型和执行的操作。更多信息,请参阅第 14.6.1 节,“算术运算符”。

13.1.1 数字数据类型语法

原文:dev.mysql.com/doc/refman/8.0/en/numeric-type-syntax.html

对于整数数据类型,M 表示最小显示宽度。最大显示宽度为 255。显示宽度与类型可以存储的值范围无关,如 第 13.1.6 节,“数字类型属性” 中所述。

对于浮点和定点数据类型,M 是可以存储的总位数。

截至 MySQL 8.0.17 版本,整数数据类型的显示宽度属性已被弃用;您应该预期在未来的 MySQL 版本中将其移除。

如果为数字列指定了 ZEROFILL,MySQL 会自动向列添加 UNSIGNED 属性。

截至 MySQL 8.0.17 版本,ZEROFILL 属性对于数字数据类型已被弃用;您应该预期在未来的 MySQL 版本中将其移除。考虑使用其他方法来产生此属性的效果。例如,应用程序可以使用 LPAD() 函数将数字零填充到所需宽度,或者它们可以将格式化的数字存储在 CHAR 列中。

允许 UNSIGNED 属性的数字数据类型也允许 SIGNED。但是,这些数据类型默认为有符号,因此 SIGNED 属性没有效果。

截至 MySQL 8.0.17 版本,UNSIGNED 属性对于 FLOATDOUBLEDECIMAL(以及任何同义词)列已被弃用;您应该预期在未来的 MySQL 版本中将其移除。考虑为这些列使用简单的 CHECK 约束代替。

SERIALBIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE 的别名。

在整数列的定义中,SERIAL DEFAULT VALUENOT NULL AUTO_INCREMENT UNIQUE 的别名。

警告

当您在一个类型为 UNSIGNED 的整数值之间进行减法运算时,结果是无符号的,除非启用了 NO_UNSIGNED_SUBTRACTION SQL 模式。参见 第 14.10 节,“转换函数和运算符”。

  • BIT[(*M*)]

    位值类型。M 表示每个值的位数,从 1 到 64。如果省略 M,默认值为 1。

  • TINYINT[(*M*)] [UNSIGNED] [ZEROFILL]

    非常小的整数。有符号范围为 -128127。无符号范围为 0255

  • BOOL, BOOLEAN

    这些类型是TINYINT(1)的同义词。零值被视为假。非零值被视为真:

    mysql> SELECT IF(0, 'true', 'false');
    +------------------------+
    | IF(0, 'true', 'false') |
    +------------------------+
    | false                  |
    +------------------------+
    
    mysql> SELECT IF(1, 'true', 'false');
    +------------------------+
    | IF(1, 'true', 'false') |
    +------------------------+
    | true                   |
    +------------------------+
    
    mysql> SELECT IF(2, 'true', 'false');
    +------------------------+
    | IF(2, 'true', 'false') |
    +------------------------+
    | true                   |
    +------------------------+
    

    然而,值TRUEFALSE仅仅是10的别名,如下所示:

    mysql> SELECT IF(0 = FALSE, 'true', 'false');
    +--------------------------------+
    | IF(0 = FALSE, 'true', 'false') |
    +--------------------------------+
    | true                           |
    +--------------------------------+
    
    mysql> SELECT IF(1 = TRUE, 'true', 'false');
    +-------------------------------+
    | IF(1 = TRUE, 'true', 'false') |
    +-------------------------------+
    | true                          |
    +-------------------------------+
    
    mysql> SELECT IF(2 = TRUE, 'true', 'false');
    +-------------------------------+
    | IF(2 = TRUE, 'true', 'false') |
    +-------------------------------+
    | false                         |
    +-------------------------------+
    
    mysql> SELECT IF(2 = FALSE, 'true', 'false');
    +--------------------------------+
    | IF(2 = FALSE, 'true', 'false') |
    +--------------------------------+
    | false                          |
    +--------------------------------+
    

    最后两个语句显示的结果是因为2既不等于1也不等于0

  • SMALLINT[(*M*)] [UNSIGNED] [ZEROFILL]

    一个小整数。有符号范围是-3276832767。无符号范围是065535

  • MEDIUMINT[(*M*)] [UNSIGNED] [ZEROFILL]

    一个中等大小的整数。有符号范围是-83886088388607。无符号范围是016777215

  • INT[(*M*)] [UNSIGNED] [ZEROFILL]

    一个正常大小的整数。有符号范围是-21474836482147483647。无符号范围是04294967295

  • INTEGER[(*M*)] [UNSIGNED] [ZEROFILL]

    这种类型是INT的同义词。

  • BIGINT[(*M*)] [UNSIGNED] [ZEROFILL]

    一个大整数。有符号范围是-92233720368547758089223372036854775807。无符号范围是018446744073709551615

    SERIALBIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE的别名。

    关于BIGINT列,有一些需要注意的事项:

    • 所有算术运算都是使用有符号的BIGINTDOUBLE值进行的,因此除了使用位函数外,不应使用大于9223372036854775807(63 位)的无符号大整数!如果这样做,由于将BIGINT值转换为DOUBLE时的四舍五入误差,结果中的一些最后几位可能是错误的。

      MySQL 可以在以下情况下处理BIGINT

      • 当使用整数来存储大无符号值在BIGINT列中。

      • MIN(*col_name*)MAX(*col_name*)中,其中*col_name*指的是BIGINT列。

      • 当使用操作符(+-*等)其中两个操作数都是整数时。

    • 您始终可以通过使用字符串将精确整数值存储在BIGINT列中来存储它。在这种情况下,MySQL 执行一个涉及没有中间双精度表示的字符串到数字的转换。

    • 当两个操作数都是整数值时,-+*运算符使用BIGINT算术。这意味着如果您将两个大整数相乘(或从返回整数的函数得到的结果),当结果大于9223372036854775807时,您可能会得到意外的结果。

  • DECIMAL[(*M*[,*D*])] [UNSIGNED] [ZEROFILL]

    一种紧凑的“精确”固定点数。M是总位数(精度),D是小数点后的位数(比例)。小数点和(对于负数)-符号不计入M。如果*D为 0,则值没有小数点或小数部分。DECIMAL的最大数字(M)为 65。支持的小数位数(D)的最大值为 30。如果省略D,默认值为 0。如果省略M*,默认值为 10。(DECIMAL文本的长度也有限制;请参阅第 14.24.3 节,“表达式处理”。)

    如果指定了UNSIGNED,则不允许负值。截至 MySQL 8.0.17,对于DECIMAL(以及任何同义词)列,UNSIGNED属性已被弃用;您应该期望在将来的 MySQL 版本中删除对其的支持。考虑为这些列使用简单的CHECK约束。

    所有对DECIMAL列的基本计算(+-*/)都以 65 位数字的精度进行。

  • DEC[(*M*[,*D*])] [UNSIGNED] [ZEROFILL]NUMERIC[(*M*[,*D*])] [UNSIGNED] [ZEROFILL]FIXED[(*M*[,*D*])] [UNSIGNED] [ZEROFILL]

    这些类型是DECIMAL的同义词。FIXED同义词可用于与其他数据库系统的兼容性。

  • FLOAT[(*M*,*D*)] [UNSIGNED] [ZEROFILL]

    一个小(单精度)浮点数。允许的值为-3.402823466E+38-1.175494351E-380,和1.175494351E-383.402823466E+38。这些是基于 IEEE 标准的理论极限。实际范围可能会略小,取决于您的硬件或操作系统。

    M是总位数,D是小数点后的位数。如果省略MD,则值将存储到硬件允许的极限。单精度浮点数精确到大约 7 位小数。

    FLOAT(*M*,*D*)是一个非标准的 MySQL 扩展。截至 MySQL 8.0.17 版本,此语法已被弃用,您应该期待在未来的 MySQL 版本中移除对其的支持。

    UNSIGNED,如果指定,将禁止负值。截至 MySQL 8.0.17 版本,对于FLOAT类型的列,UNSIGNED属性已被弃用(以及任何同义词),您应该期待在未来的 MySQL 版本中移除对其的支持。考虑为这些列使用简单的CHECK约束。

    在 MySQL 中,所有计算都是以双精度进行的,因此使用FLOAT可能会导致一些意外的问题。参见第 B.3.4.7 节,“解决没有匹配行的问题”。

  • FLOAT(*p*) [UNSIGNED] [ZEROFILL]

    一个浮点数。p表示位数精度,但 MySQL 仅使用此值来确定是否使用FLOATDOUBLE作为结果数据类型。如果p从 0 到 24,数据类型变为没有MD值的FLOAT。如果p从 25 到 53,数据类型变为没有MD值的DOUBLE。结果列的范围与本节前面描述的单精度FLOAT或双精度DOUBLE数据类型的范围相同。

    UNSIGNED,如果指定,将禁止负值。截至 MySQL 8.0.17 版本,对于FLOAT类型的列,UNSIGNED属性已被弃用(以及任何同义词),您应该期待在未来的 MySQL 版本中移除对其的支持。考虑为这些列使用简单的CHECK约束。

    FLOAT(*p*)语法是为了 ODBC 兼容性而提供的。

  • DOUBLE[(*M*,*D*)] [UNSIGNED] [ZEROFILL]

    一个正常大小(双精度)的浮点数。允许的值为-1.7976931348623157E+308-2.2250738585072014E-3080,以及2.2250738585072014E-3081.7976931348623157E+308。这些是基于 IEEE 标准的理论极限。实际范围可能会略小,取决于您的硬件或操作系统。

    M是总位数,D是小数点后的位数。如果省略了MD,则值将存储到硬件允许的极限。双精度浮点数精确到大约 15 位小数。

    DOUBLE(*M*,*D*)是 MySQL 的非标准扩展。截至 MySQL 8.0.17 版本,此语法已被弃用,您应该期待在未来的 MySQL 版本中移除对其的支持。

    UNSIGNED,如果指定,将不允许负值。截至 MySQL 8.0.17 版本,对于DOUBLE类型的列,UNSIGNED属性已被弃用(以及任何同义词),您应该期待在未来的 MySQL 版本中移除对其的支持。考虑为这些列使用简单的CHECK约束。

  • DOUBLE PRECISION[(*M*,*D*)] [UNSIGNED] [ZEROFILL]REAL[(*M*,*D*)] [UNSIGNED] [ZEROFILL]

    这些类型是DOUBLE的同义词。例外:如果启用了REAL_AS_FLOAT SQL 模式,则REALFLOAT的同义词,而不是DOUBLE

13.1.2 整数类型(精确值)- INTEGER、INT、SMALLINT、TINYINT、MEDIUMINT、BIGINT

原文:dev.mysql.com/doc/refman/8.0/en/integer-types.html

MySQL 支持 SQL 标准整数类型INTEGER(或INT)和SMALLINT。作为对标准的扩展,MySQL 还支持整数类型TINYINTMEDIUMINTBIGINT。以下表格显示了每种整数类型所需的存储空间和范围。

表 13.1 MySQL 支持的整数类型所需的存储空间和范围

类型存储空间(字节)最小有符号值最小无符号值最大有符号值最大无符号值
TINYINT1-1280127255
SMALLINT2-3276803276765535
MEDIUMINT3-83886080838860716777215
INT4-2147483648021474836474294967295
BIGINT8-2⁶³02⁶³-12⁶⁴-1

13.1.3 固定点类型(精确值)- DECIMAL, NUMERIC

原文:dev.mysql.com/doc/refman/8.0/en/fixed-point-types.html

DECIMALNUMERIC类型存储精确的数值数据。当需要保留精确精度时,例如在货币数据中,使用这些类型。在 MySQL 中,NUMERIC被实现为DECIMAL,因此关于DECIMAL的以下说明同样适用于NUMERIC

MySQL 以二进制格式存储DECIMAL值。请参阅第 14.24 节,“精度数学”。

DECIMAL列声明中,通常会指定精度和标度。例如:

salary DECIMAL(5,2)

在这个例子中,5是精度,2是标度。精度表示存储值的有效数字的数量,而标度表示小数点后可以存储的数字的数量。

标准 SQL 要求DECIMAL(5,2)能够存储任何具有五位数字和两位小数的值,因此可以存储在salary列中的值范围从-999.99999.99

在标准 SQL 中,语法DECIMAL(*M*)等同于DECIMAL(*M*,0)。类似地,语法DECIMAL等同于DECIMAL(*M*,0),其中实现允许决定*M的值。MySQL 支持DECIMAL语法的这两种变体形式。M*的默认值为 10。

如果标度为 0,则DECIMAL值不包含小数点或小数部分。

DECIMAL的最大数字位数为 65,但给定DECIMAL列的实际范围可以受到给定列的精度或标度的限制。当为这样的列分配一个具有比指定标度允许的更多小数位数的值时,该值将被转换为该标度。(具体行为取决于操作系统,但通常效果是截断为允许的数字位数。)

13.1.4 浮点类型(近似值) - FLOAT, DOUBLE

原文:dev.mysql.com/doc/refman/8.0/en/floating-point-types.html

FLOATDOUBLE 类型表示近似数值数据。MySQL 使用四个字节来存储单精度值,使用八个字节来存储双精度值。

对于 FLOAT,SQL 标准允许在关键字 FLOAT 后面的括号中指定精度(但不是指数范围)的可选规范,即 FLOAT(*p*)。MySQL 也支持这种可选精度规范,但在 FLOAT(*p*) 中的精度值仅用于确定存储大小。精度从 0 到 23 会导致一个 4 字节的单精度 FLOAT 列。精度从 24 到 53 会导致一个 8 字节的双精度 DOUBLE 列。

MySQL 允许非标准的语法:FLOAT(*M*,*D*)REAL(*M*,*D*)DOUBLE PRECISION(*M*,*D*)。这里,(*M*,*D*) 意味着值可以以最多 M 位数字的形式存储,其中 D 位可以在小数点后面。例如,定义为 FLOAT(7,4) 的列显示为 -999.9999。当存储值时,MySQL 进行四舍五入,因此如果你将 999.00009 插入到 FLOAT(7,4) 列中,近似结果是 999.0001

从 MySQL 8.0.17 开始,非标准的 FLOAT(*M*,*D*)DOUBLE(*M*,*D*) 语法已被弃用,你应该预期在未来的 MySQL 版本中将不再支持它。

因为浮点值是近似值,而不是精确值,试图在比较中将它们视为精确值可能会导致问题。它们也受平台或实现的依赖性影响。更多信息,请参见 Section B.3.4.8, “浮点值的问题”。

为了最大的可移植性,需要存储近似数值数据的代码应该使用 FLOATDOUBLE PRECISION,不需要指定精度或数字位数。

13.1.5 比特值类型 - BIT

原文:dev.mysql.com/doc/refman/8.0/en/bit-type.html

BIT数据类型用于存储比特值。BIT(*M*)类型可以存储*M位值。M*的取值范围为 1 到 64。

要指定比特值,可以使用b'*value*'表示法。*value*是用零和一写成的二进制值。例如,b'111'b'10000000'分别表示 7 和 128。参见第 11.1.5 节,“比特值文字”。

如果给一个长度为BIT(*M*)的列赋值,而该值长度小于*M*位,那么该值将在左侧用零填充。例如,给一个BIT(6)列赋值为b'101',实际上等同于赋值为b'000101'

**NDB Cluster. ** 在给定的NDB表中使用的所有BIT列的最大组合大小不能超过 4096 位。

13.1.6 数字类型属性

原文:dev.mysql.com/doc/refman/8.0/en/numeric-type-attributes.html

MySQL 支持一个扩展,可选择在类型的基本关键字后面的括号中指定整数数据类型的显示宽度。例如,INT(4) 指定了一个显示宽度为四位数的 INT。应用程序可以使用这个可选的显示宽度来显示宽度小于列指定的宽度的整数值,通过左侧用空格填充它们。(也就是说,这个宽度存在于返回结果集的元数据中。是否使用取决于应用程序。)

显示宽度限制可以存储在列中的值的范围。也不会阻止比列显示宽度更宽的值正确显示。例如,指定为 SMALLINT(3) 的列具有 -3276832767 的通常 SMALLINT 范围,超出三位数允许范围的值将使用超过三位数的完整显示。

当与可选的(非标准的)ZEROFILL 属性一起使用时,默认的空格填充被零替换。例如,对于声明为 INT(4) ZEROFILL 的列,检索到的值为 5 会显示为 0005

注意

ZEROFILL 属性在涉及表达式或 UNION 查询的列中被忽略。

如果您在具有 ZEROFILL 属性的整数列中存储大于显示宽度的值,当 MySQL 为一些复杂的连接生成临时表时,可能会遇到问题。在这些情况下,MySQL 假定数据值适合列显示宽度内。

从 MySQL 8.0.17 开始,ZEROFILL 属性对于数字数据类型已被弃用,整数数据类型的显示宽度属性也是如此。您应该期望在未来的 MySQL 版本中删除对整数数据类型的 ZEROFILL 和显示宽度的支持。考虑使用其他方法来产生这些属性的效果。例如,应用程序可以使用 LPAD() 函数将数字零填充到所需的宽度,或者它们可以将格式化的数字存储在 CHAR 列中。

所有整数类型都可以具有可选的(非标准的)UNSIGNED属性。无符号类型可用于在列中仅允许非负数或在需要列的较大上限数值范围时使用。例如,如果INT列是UNSIGNED,则列范围的大小相同,但其端点向上移动,从-2147483648214748364704294967295

浮点和定点类型也可以是UNSIGNED。与整数类型一样,此属性防止负值存储在列中。与整数类型不同,列值的上限范围保持不变。从 MySQL 8.0.17 开始,对于FLOATDOUBLEDECIMAL(以及任何同义词)类型的列,UNSIGNED属性已被弃用,您应该期望在将来的 MySQL 版本中删除对其的支持。考虑为这些列使用简单的CHECK约束。

如果为数字列指定ZEROFILL,MySQL 会自动添加UNSIGNED属性。

整数或浮点数据类型可以具有AUTO_INCREMENT属性。当您将NULL值插入到索引的AUTO_INCREMENT列中时,该列将设置为下一个序列值。通常情况下,这是*value*+1,其中*value*是当前表中该列的最大值。(AUTO_INCREMENT序列从1开始。)

0存储到AUTO_INCREMENT列中与存储NULL具有相同效果,除非启用了NO_AUTO_VALUE_ON_ZERO SQL 模式。

插入NULL以生成AUTO_INCREMENT值要求该列声明为NOT NULL。如果列声明为NULL,插入NULL将存储一个NULL。当您将任何其他值插入到AUTO_INCREMENT列中时,该列将设置为该值,并且序列将被重置,以便下一个自动生成的值从插入的值顺序生成。

不支持为AUTO_INCREMENT列使用负值。

CHECK约束不能引用具有AUTO_INCREMENT属性的列,也不能将AUTO_INCREMENT属性添加到已用于CHECK约束的现有列中。

截至 MySQL 8.0.17 版本,对于 FLOATDOUBLE 列,AUTO_INCREMENT 支持已被弃用;你应该期待在未来的 MySQL 版本中将其移除。考虑从这些列中移除 AUTO_INCREMENT 属性,或将其转换为整数类型。

13.1.7 超出范围和溢出处理

原文:dev.mysql.com/doc/refman/8.0/en/out-of-range-and-overflow.html

当 MySQL 将一个值存储在数值列中,该值超出了列数据类型的允许范围时,结果取决于当时生效的 SQL 模式:

  • 如果启用了严格的 SQL 模式,MySQL 将拒绝超出范围的值并显示错误,插入操作将失败,符合 SQL 标准。

  • 如果未启用任何限制模式,MySQL 会将值截断到列数据类型范围的适当端点,并存储结果值。

    当将超出范围的值分配给整数列时,MySQL 会存储代表列数据类型范围相应端点的值。

    当浮点或定点列被分配一个超出指定(或默认)精度和标度所暗示范围的值时,MySQL 会存储代表该范围端点的值。

假设表 t1 定义如下:

CREATE TABLE t1 (i1 TINYINT, i2 TINYINT UNSIGNED);

当启用严格的 SQL 模式时,会发生超出范围的错误:

mysql> SET sql_mode = 'TRADITIONAL';
mysql> INSERT INTO t1 (i1, i2) VALUES(256, 256);
ERROR 1264 (22003): Out of range value for column 'i1' at row 1
mysql> SELECT * FROM t1;
Empty set (0.00 sec)

当未启用严格的 SQL 模式时,会发生截断并伴有警告:

mysql> SET sql_mode = '';
mysql> INSERT INTO t1 (i1, i2) VALUES(256, 256);
mysql> SHOW WARNINGS;
+---------+------+---------------------------------------------+
| Level   | Code | Message                                     |
+---------+------+---------------------------------------------+
| Warning | 1264 | Out of range value for column 'i1' at row 1 |
| Warning | 1264 | Out of range value for column 'i2' at row 1 |
+---------+------+---------------------------------------------+
mysql> SELECT * FROM t1;
+------+------+
| i1   | i2   |
+------+------+
|  127 |  255 |
+------+------+

当未启用严格的 SQL 模式时,由于截断而发生的列赋值转换会作为警告报告给ALTER TABLELOAD DATAUPDATE 和多行INSERT 语句。在严格模式下,这些语句将失败,并且根据表是否为事务表和其他因素,某些或全部值将不会被插入或更改。有关详细信息,请参见第 7.1.11 节,“服务器 SQL 模式”。

在数值表达式评估过程中发生溢出会导致错误。例如,最大的有符号BIGINT - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT") 值为 9223372036854775807,因此以下表达式会产生错误:

mysql> SELECT 9223372036854775807 + 1;
ERROR 1690 (22003): BIGINT value is out of range in '(9223372036854775807 + 1)'

要使此操作在此情况下成功,将值转换为无符号;

mysql> SELECT CAST(9223372036854775807 AS UNSIGNED) + 1;
+-------------------------------------------+
| CAST(9223372036854775807 AS UNSIGNED) + 1 |
+-------------------------------------------+
|                       9223372036854775808 |
+-------------------------------------------+

溢出是否发生取决于操作数的范围,因此处理前述表达式的另一种方法是使用精确值算术,因为DECIMAL - DECIMAL, NUMERIC") 值的范围比整数大:

mysql> SELECT 9223372036854775807.0 + 1;
+---------------------------+
| 9223372036854775807.0 + 1 |
+---------------------------+
|     9223372036854775808.0 |
+---------------------------+

两个整数值相减,其中一个为UNSIGNED类型,默认会产生无符号结果。如果结果本应为负数,则会产生错误:

mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT CAST(0 AS UNSIGNED) - 1;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(cast(0 as unsigned) - 1)'

如果启用了NO_UNSIGNED_SUBTRACTION SQL 模式,则结果为负数:

mysql> SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
mysql> SELECT CAST(0 AS UNSIGNED) - 1;
+-------------------------+
| CAST(0 AS UNSIGNED) - 1 |
+-------------------------+
|                      -1 |
+-------------------------+

如果这样的操作结果用于更新一个UNSIGNED整数列,结果将被截断为列类型的最大值,或者如果启用了NO_UNSIGNED_SUBTRACTION,则被截断为 0。如果启用了严格的 SQL 模式,将会发生错误并且列保持不变。

13.2 日期和时间数据类型

原文:dev.mysql.com/doc/refman/8.0/en/date-and-time-types.html

13.2.1 日期和时间数据类型语法

13.2.2 DATE、DATETIME 和 TIMESTAMP 类型

13.2.3 TIME 类型

13.2.4 YEAR 类型

13.2.5 TIMESTAMP 和 DATETIME 的自动初始化和更新

13.2.6 时间值中的小数秒

13.2.7 MySQL 使用的是哪种日历?

13.2.8 日期和时间类型之间的转换

13.2.9 日期中的两位数年份

用于表示时间值的日期和时间数据类型是DATETIMEDATETIMETIMESTAMPYEAR。每种时间类型都有一系列有效值,以及一个“零”值,当您指定 MySQL 无法表示的无效值时可以使用。TIMESTAMPDATETIME 类型具有特殊的自动更新行为,详见第 13.2.5 节,“TIMESTAMP 和 DATETIME 的自动初始化和更新”。

有关时间数据类型的存储要求的信息,请参见第 13.7 节,“数据类型存储要求”。

有关操作时间值的函数的描述,请参见第 14.7 节,“日期和时间函数”。

在处理日期和时间类型时,请记住以下一般考虑事项:

  • MySQL 以标准输出格式检索给定日期或时间类型的值,但它尝试解释您提供的各种输入值的格式(例如,当您指定要分配给或与日期或时间类型进行比较的值时)。有关日期和时间类型允许的格式的描述,请参见第 11.1.3 节,“日期和时间文字”。预期您提供有效值。如果您使用其他格式的值,可能会导致不可预测的结果。

  • 尽管 MySQL 尝试以几种格式解释值,但日期部分必须始终按年-月-日的顺序给出(例如,'98-09-04'),而不是在其他地方通常使用的月-日-年或日-月-年的顺序(例如,'09-04-98''04-09-98')。要将其他顺序的字符串转换为年-月-日顺序,可能会有用的是STR_TO_DATE() 函数。

  • 包含 2 位年份值的日期是模棱两可的,因为世纪是未知的。MySQL 使用以下规则解释 2 位年份值:

    • 范围在 70-99 的年份值变为 1970-1999

    • 范围在 00-69 的年份值变为 2000-2069

    另请参阅第 13.2.9 节,“日期中的 2 位年份”。

  • 从一个时间类型转换为另一个时间类型的值转换遵循第 13.2.8 节,“日期和时间类型之间的转换”中的规则。

  • 如果将日期或时间值用于数字上下文中,MySQL 将自动将其转换为数字,反之亦然。

  • 默认情况下,当 MySQL 遇到超出范围或其他类型无效的日期或时间类型的值时,它将该值转换为该类型的“零”值。例外情况是,超出范围的TIME值将被剪切到TIME范围的适当端点。

  • 通过将 SQL 模式设置为适当的值,您可以更准确地指定 MySQL 支持的日期类型。(参见第 7.1.11 节,“服务器 SQL 模式”。)您可以通过启用ALLOW_INVALID_DATES SQL 模式,使 MySQL 接受某些日期,例如 '2009-11-31'。当您希望将用户指定的“可能错误”的值(例如在 Web 表单中)存储在数据库中以供将来处理时,这将非常有用。在此模式下,MySQL 仅验证月份在 1 到 12 的范围内,日期在 1 到 31 的范围内。

  • MySQL 允许您在DATEDATETIME列中存储日期,其中日期或月份和日期为零。这对于需要存储生日但可能不知道确切日期的应用程序非常有用。在这种情况下,您只需将日期存储为 '2009-00-00''2009-01-00'。但是,对于这样的日期,您不应该期望对于需要完整日期的函数(例如DATE_SUB()DATE_ADD())获得正确的结果。要禁止日期中的零月份或日期部分,启用NO_ZERO_IN_DATE 模式。

  • MySQL 允许您将“零”值'0000-00-00'存储为“虚拟日期”。在某些情况下,这比使用NULL值更方便,并且使用的数据和索引空间更少。要禁止'0000-00-00',请启用NO_ZERO_DATE模式。

  • “Zero”日期或时间值在 Connector/ODBC 中使用时会自动转换为NULL,因为 ODBC 无法处理这些值。

以下表格显示了每种类型的“零”值的格式。这些“零”值是特殊的,但您可以使用表中显示的值显式存储或引用它们。您还可以使用更容易写的值'0'0来做到这一点。对于包含日期部分的时间类型(日期日期时间时间戳),使用这些值可能会产生警告或错误。具体行为取决于启用的严格和NO_ZERO_DATE SQL 模式中的哪些;请参阅第 7.1.11 节,“服务器 SQL 模式”。

数据类型“零”值
日期'0000-00-00'
时间'00:00:00'
日期时间'0000-00-00 00:00:00'
时间戳'0000-00-00 00:00:00'
年份0000

13.2.1 日期和时间数据类型语法

原文:dev.mysql.com/doc/refman/8.0/en/date-and-time-type-syntax.html

用于表示时间值的日期和时间数据类型是 DATETIMEDATETIMETIMESTAMPYEAR

对于 DATEDATETIME 范围描述,“支持” 表示虽然较早的值可能有效,但不保证。

MySQL 允许 TIMEDATETIMETIMESTAMP 值具有微秒(6 位数字)精度的小数秒。要定义包含小数秒部分的列,请使用语法 *type_name*(*fsp*),其中 type_nameTIMEDATETIMETIMESTAMPfsp 是小数秒精度。例如:

CREATE TABLE t1 (t TIME(3), dt DATETIME(6), ts TIMESTAMP(0));

fsp 值(如果提供)必须在 0 到 6 的范围内。值为 0 表示没有小数部分。如果省略,则默认精度为 0。(这与标准 SQL 默认值 6 不同,以保持与之前 MySQL 版本的兼容性。)

表中的任何 TIMESTAMPDATETIME 列都可以具有自动初始化和更新属性;请参阅 第 13.2.5 节,“TIMESTAMP 和 DATETIME 的自动初始化和更新”。

  • DATE

    日期。支持的范围是 '1000-01-01''9999-12-31'。MySQL 以 '*YYYY-MM-DD*' 格式显示 DATE 值,但允许将值分配给 DATE 列,使用字符串或数字。

  • DATETIME[(*fsp*)]

    日期和时间的组合。支持范围为'1000-01-01 00:00:00.000000''9999-12-31 23:59:59.499999'。MySQL 以'*YYYY-MM-DD hh:mm:ss*[.*fraction*]'格式显示DATETIME值,但允许将值分配给DATETIME列,使用字符串或数字。

    可以给出范围从 0 到 6 的可选*fsp*值,以指定小数秒精度。值为 0 表示没有小数部分。如果省略,则默认精度为 0。

    自动初始化和更新DATETIME列到当前日期和时间可以使用DEFAULTON UPDATE列定义子句来指定,如第 13.2.5 节,“TIMESTAMP 和 DATETIME 的自动初始化和更新”中所述。

  • TIMESTAMP[(*fsp*)]

    时间戳。范围为'1970-01-01 00:00:01.000000' UTC 到'2038-01-19 03:14:07.499999' UTC。TIMESTAMP值存储为自纪元('1970-01-01 00:00:00' UTC)以来的秒数。TIMESTAMP不能表示值'1970-01-01 00:00:00',因为那相当于自纪元以来的 0 秒,值 0 保留用于表示'0000-00-00 00:00:00',即“零”TIMESTAMP值。

    可以给出范围从 0 到 6 的可选*fsp*值,以指定小数秒精度。值为 0 表示没有小数部分。如果省略,则默认精度为 0。

    服务器处理TIMESTAMP定义的方式取决于explicit_defaults_for_timestamp系统变量的值(参见第 7.1.8 节,“服务器系统变量”)。

    如果启用explicit_defaults_for_timestamp,则不会自动将DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP属性分配给任何TIMESTAMP列。它们必须明确包含在列定义中。此外,任何未明确声明为NOT NULLTIMESTAMP允许NULL值。

    如果禁用explicit_defaults_for_timestamp,服务器处理TIMESTAMP如下:

    除非另有说明,否则表中的第一个TIMESTAMP列被定义为在未明确分配值的情况下自动设置为最近修改的日期和时间。这使得TIMESTAMP对于记录INSERTUPDATE操作的时间戳非常有用。您还可以通过将其分配为NULL值将任何TIMESTAMP列设置为当前日期和时间,除非已使用NULL属性定义允许NULL值。

    可以使用DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP列定义子句指定自动初始化和更新为当前日期和时间。默认情况下,第一个TIMESTAMP列具有这些属性,如前所述。但是,表中的任何TIMESTAMP列都可以定义为具有这些属性。

  • TIME[(*fsp*)]

    一个时间。范围是'-838:59:59.000000''838:59:59.000000'。MySQL 以'*hh:mm:ss*[.*fraction*]'格式显示TIME值,但允许使用字符串或数字将值分配给TIME列。

    可以给出范围为 0 到 6 的可选*fsp*值以指定小数秒精度。值为 0 表示没有小数部分。如果省略,则默认精度为 0。

  • YEAR[(4)]

    以 4 位数字格式表示的年份。MySQL 以*YYYY*格式显示YEAR值,但允许使用字符串或数字将值分配给YEAR列。值显示为19012155,或0000

    有关YEAR显示格式和输入值解释的其他信息,请参见第 13.2.4 节,“年份类型”。

    注意

    截至 MySQL 8.0.19,带有显式显示宽度的YEAR(4)数据类型已被弃用;您应该期望在未来的 MySQL 版本中删除对其的支持。取而代之,请使用没有显示宽度的YEAR,其含义相同。

    MySQL 8.0 不支持旧版本 MySQL 中允许的 2 位数YEAR(2)数据类型。有关转换为 4 位数YEAR的说明,请参见 2-Digit YEAR(2) Limitations and Migrating to 4-Digit YEAR,在 MySQL 5.7 参考手册中。

SUM()AVG()聚合函数不适用于时间值。(它们将值转换为数字,丢失第一个非数字字符后的所有内容。)为解决此问题,需将其转换为数字单位,执行聚合操作,然后再转换回时间值。示例:

SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(*time_col*))) FROM *tbl_name*;
SELECT FROM_DAYS(SUM(TO_DAYS(*date_col*))) FROM *tbl_name*;

13.2.2 日期、日期时间和时间戳类型

原文:dev.mysql.com/doc/refman/8.0/en/datetime.html

DATEDATETIMETIMESTAMP类型是相关的。本节描述它们的特征,它们的相似之处以及它们的区别。MySQL 以几种格式识别DATEDATETIMETIMESTAMP值,描述在第 11.1.3 节,“日期和时间文字”中。对于DATEDATETIME范围描述,“支持”表示尽管较早的值可能有效,但不能保证。

DATE类型用于具有日期部分但没有时间部分的值。MySQL 以'*YYYY-MM-DD*'格式检索和显示DATE值。支持的范围是'1000-01-01''9999-12-31'

DATETIME类型用于包含日期和时间部分的值。MySQL 以'*YYYY-MM-DD hh:mm:ss*'格式检索和显示DATETIME值。支持的范围是'1000-01-01 00:00:00''9999-12-31 23:59:59'

TIMESTAMP数据类型用于包含日期和时间部分的值。TIMESTAMP的范围是'1970-01-01 00:00:01' UTC 到'2038-01-19 03:14:07' UTC。

DATETIMETIMESTAMP值可以包含高达微秒(6 位数字)精度的尾随小数秒部分。特别是,插入到DATETIMETIMESTAMP列中的值中的任何小数部分都会被存储而不是丢弃。包含小数部分时,这些值的格式为'*YYYY-MM-DD hh:mm:ss*[.*fraction*]'DATETIME值的范围是'1000-01-01 00:00:00.000000''9999-12-31 23:59:59.499999'TIMESTAMP值的范围是'1970-01-01 00:00:01.000000''2038-01-19 03:14:07.499999'。小数部分应始终用小数点与时间的其余部分分隔;不识别其他小数秒分隔符。有关 MySQL 中对小数秒的支持的信息,请参见第 13.2.6 节,“时间值中的小数秒”。

TIMESTAMPDATETIME数据类型提供自动初始化和更新到当前日期和时间。有关更多信息,请参见第 13.2.5 节,“时间戳和日期时间的自动初始化和更新”。

MySQL 将TIMESTAMP值从当前时区转换为 UTC 进行存储,然后从 UTC 转换回当前时区进行检索。(对于DATETIME等其他类型,不会发生这种情况。)默认情况下,每个连接的当前时区是服务器的时区。时区可以根据每个连接设置。只要时区设置保持不变,您将获得与存储的相同值。如果存储了TIMESTAMP值,然后更改时区并检索该值,则检索到的值与存储的值不同。这是因为在两个方向的转换中没有使用相同的时区。当前时区可作为time_zone系统变量的值获得。有关更多信息,请参阅第 7.1.15 节,“MySQL 服务器时区支持”。

在 MySQL 8.0.19 及更高版本中,您可以在将TIMESTAMPDATETIME值插入表时指定时区偏移量。有关更多信息和示例,请参阅第 11.1.3 节,“日期和时间文字”。

如果 SQL 模式允许此转换,则无效的DATEDATETIMETIMESTAMP值将被转换为相应类型的“零”值('0000-00-00''0000-00-00 00:00:00')。具体行为取决于是否启用了严格 SQL 模式和NO_ZERO_DATE SQL 模式中的哪一个;请参阅第 7.1.11 节,“服务器 SQL 模式”。

在 MySQL 8.0.22 及更高版本中,您可以使用带有AT TIME ZONE运算符的CAST()TIMESTAMP值转换为 UTCDATETIME值,如下所示:

mysql> SELECT col,
     >     CAST(col AT TIME ZONE INTERVAL '+00:00' AS DATETIME) AS ut
     >     FROM ts ORDER BY id;
+---------------------+---------------------+
| col                 | ut                  |
+---------------------+---------------------+
| 2020-01-01 10:10:10 | 2020-01-01 15:10:10 |
| 2019-12-31 23:40:10 | 2020-01-01 04:40:10 |
| 2020-01-01 13:10:10 | 2020-01-01 18:10:10 |
| 2020-01-01 10:10:10 | 2020-01-01 15:10:10 |
| 2020-01-01 04:40:10 | 2020-01-01 09:40:10 |
| 2020-01-01 18:10:10 | 2020-01-01 23:10:10 |
+---------------------+---------------------+

有关语法和其他示例的完整信息,请参阅CAST()函数的描述。

要注意 MySQL 中日期值解释的某些属性:

  • MySQL 允许以字符串形式指定的值采用“宽松”格式,在这种格式中,任何标点符号都可以用作日期部分或时间部分之间的分隔符。在某些情况下,这种语法可能会产生误导。例如,像'10:11:12'这样的值可能看起来像一个时间值,因为有:,但如果在日期上下文中使用,则会被解释为年份'2010-11-12'。值'10:45:15'会被转换为'0000-00-00',因为'45'不是一个有效的月份。

    在日期和时间部分与小数秒部分之间唯一识别的分隔符是小数点。

  • 服务器要求月份和日期值有效,而不仅仅是在 1 到 12 和 1 到 31 的范围内。在禁用严格模式的情况下,无效日期如'2004-04-31'会被转换为'0000-00-00'并生成警告。启用严格模式时,无效日期会生成错误。要允许这样的日期,启用ALLOW_INVALID_DATES。更多信息请参见 Section 7.1.11, “Server SQL Modes”。

  • MySQL 不接受在日期或月份列中包含零或不是有效日期的TIMESTAMP值。唯一的例外是特殊的“零”值'0000-00-00 00:00:00',如果 SQL 模式允许这个值。具体行为取决于是否启用了严格 SQL 模式和NO_ZERO_DATE SQL 模式中的哪一个;参见 Section 7.1.11, “Server SQL Modes”。

  • 包含 2 位数年份值的日期是模棱两可的,因为世纪未知。MySQL 使用以下规则解释 2 位数年份值:

    • 范围在00-69的年份值变为2000-2069

    • 范围在70-99的年份值变为1970-1999

    另请参见 Section 13.2.9, “2-Digit Years in Dates”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值