Tipos de datos MySQL - documentos oficiales - notas de estudio - valores numéricos, fecha y hora, cadenas, json

Tipos de datos MySQL-documentos oficiales-notas de estudio

Tabla de contenido

MySQL admite varios tipos de datos SQL : tipos numéricos, tipos de fecha y hora, tipos de cadenas (caracteres y bytes), tipos espaciales y JSONtipos de datos. Este capítulo proporciona una descripción general y una descripción más detallada de las propiedades de tipo en cada categoría, así como un resumen de los requisitos de almacenamiento de tipos de datos.

Las descripciones de tipos de datos utilizan las siguientes convenciones:

  • Para tipos de números enteros, * M* representa el ancho máximo de visualización. Para los tipos de punto flotante y punto fijo, ** Mes el número total de bits que se pueden almacenar (precisión). Para tipos de cadena, * Mes la longitud máxima. MEl valor máximo permitido de * depende del tipo de datos.

  • * D*Aplicable a los tipos de punto flotante y punto fijo, que indica el número de dígitos después del punto decimal (número de decimales). El valor máximo posible es 30, pero no debe ser mayor que M-2.

  • * fsp* Se aplica a TIME, DATETIMEy TIMESTAMPescribe y representa la precisión de fracciones de segundo; es decir, el número de fracciones de segundo después del punto decimal. El fspvalor **, si se proporciona, debe estar en el rango de 0 a 6. Un valor de 0 significa que no hay parte decimal. Si se omite, la precisión predeterminada es 0. (Esto es diferente del valor predeterminado de SQL estándar de 6 por compatibilidad con versiones anteriores de MySQL).

  • Los corchetes ( [y ]) representan partes opcionales de la definición de tipo.

1. Tipo de datos numéricos

1.1 Sintaxis de tipos de datos numéricos

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

1.3 定点类型(精确值)——DECIMAL、NUMERIC

1.4 浮点类型(近似值)——FLOAT、DOUBLE

1.5 位值类型——BIT

1.6 数值类型属性

1.7 超出范围和溢出处理

MySQL 支持所有标准 SQL 数字数据类型。
这些类型包括精确数值数据类型(INTEGER、 SMALLINT、 DECIMAL 和 NUMERIC ),以及近似数值数据类型(FLOAT、 REAL 和 DOUBLE PRECISION)。
关键字 INT 是 INTEGER 的同义词,
关键字 DEC 和 FIXED 是 DECIMAL 的同义词,
MySQL 将 DOUBLE 视为 DOUBLE PRECISION (非标准扩展)的同义词,
MySQL 也将 REAL 视为 DOUBLE PRECISION (非标准变体)的同义词,除非启用了 REAL_AS_FLOAT 的 SQL 模式。

数据类型 BIT 存储“位”值,并支持 MyISAM、InnoDB、 MEMORY和 NDB表。

1.1 数值数据类型的语法

  • 对于整数数据类型,M表示最大显示宽度。最大显示宽度为 255。显示宽度与类型可以存储的值的范围无关。int(M) 例子: int(4) 表示最大显示4位数字,即个位、十位、百位和千位
  • 对于浮点和定点数据类型, M是可以存储的总位数(包含了小数部分),这里的“位”与bit不是同一个概念,这里的“位”指的是数字的位数,即个位、十位等。
    • Punto fijo: decimal(M[,D])Ejemplo: decimal(1)Indica que mysql solo almacena números enteros de 1 dígito
    • Punto flotante: float(M[,D])Ejemplo: float(1)indica que mysql solo almacena números enteros de 1 dígito

Si especifica ZEROFILL para una columna numérica, MySQL agrega automáticamente el atributo UNSIGNED a la columna.

Los tipos de datos numéricos permiten propiedades SIN FIRMAR y FIRMADA. Sin embargo, estos tipos de datos están firmados de forma predeterminada, por lo que el atributo SIGNED no tiene ningún efecto.

SERIAL DEFAULT VALUE es un alias de NOT NULL AUTO_INCREMENT UNIQUE en la definición de una columna de números enteros.

Advertencia
Cuando utiliza la resta entre valores enteros de tipo UNSIGNED, el resultado no está firmado a menos que el modo SQL NO_UNSIGNED_SUBTRACTION esté habilitado.

1.1.1BIT[(M)]

Tipo de valor de bit. MRepresenta el número de dígitos de cada valor, desde 1hasta 64. Si Mse omite, el valor predeterminado es 1.

1.1.2TINYINT[(M)] [UNSIGNED] [ZEROFILL]

Un entero muy pequeño que ocupa 1bytes. El rango con signo es -2[^7] = -128a 2[^7]-1 = 127. El rango sin signo es 02[^8]-1 = 255.
MIndica el ancho máximo de visualización.

1.1.3 BOOL,BOOLEAN

Estos tipos son TINYINT(1)sinónimos de . Se considera un valor de cero . Se consideran valores distintos de cero :

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                   |
+------------------------+

Sin embargo, los valores TRUEy FALSEson solo alias de 1y 0, respectivamente de la siguiente manera:

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                          |
+--------------------------------+

Las dos últimas declaraciones muestran el resultado de 2no igual a TRUEy FALSEporque 2ni es igual 1ni igual a 0.

1.1.4SMALLINT[(M)] [UNSIGNED] [ZEROFILL]

Un número entero pequeño que ocupa 2bytes. El rango con signo es -2[^15] = -32768a 2[^15]-1 = 32767. El rango sin signo es 02[^16]-1 = 65535.

1.1.5MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]

Un número entero de tamaño mediano en 3bytes. El rango con signo es -2[^23] = -8388608a 2[^23]-1 = 8388607. El rango sin signo es 02[^24]-1 = 16777215.

1.1.6INT[(M)] [UNSIGNED] [ZEROFILL]

Un número entero de tamaño normal, en 4bytes. El rango con signo es -2[^31] = -2147483648a 2[^31]-1 = 2147483647. El rango sin signo es 02[^32]-1 = 4294967295.

1.1.7INTEGER[(M)] [UNSIGNED] [ZEROFILL]

Este tipo es INTsinónimo de .

1.1.8BIGINT[(M)] [UNSIGNED] [ZEROFILL]

Un número entero grande que ocupa 8bytes. El rango con signo es -2[^63] = -9223372036854775808a 2[^63]-1 = 9223372036854775807. El rango sin signo es 02[^64]-1 = 18446744073709551615.

SERIALBIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUEalias.

BIGINTAlgunas cosas que debes tener en cuenta sobre las columnas :

  • Toda la aritmética se realiza utilizando valores BIGINTOR con signo, por lo que no debe utilizar números enteros grandes sin signo mayores que (63 bits), ¡excepto para funciones de bits! Si hace esto, algunos de los últimos números del resultado pueden ser incorrectos debido a errores de redondeo al convertir el valor aDOUBLE9223372036854775807BIGINTDOUBLE

    MySQL puede manejar BIGINTlas siguientes situaciones:

    • Cuando se utilizan números enteros BIGINTpara almacenar valores grandes sin signo en columnas.
    • BIGINTCuando se utilizan columnas en MIN(*col_name*) y MAX(*col_name*)
    • Cuando se utiliza un operador donde ambos operandos son números enteros ( +, -, *etc.).
  • BIGINTSiempre es posible almacenar valores enteros exactos utilizando una cadena para asignarlos a una columna. En este caso, MySQL realiza una conversión de cadena a número que no implica una doble representación intermedia.

  • Los operadores , y utilizan aritmética -cuando ambos operandos son valores enteros . Esto significa que si multiplica dos números enteros grandes (o el resultado de una función que devuelve un número entero), puede obtener resultados inesperados cuando el resultado sea mayor que .+*BIGINT9223372036854775807

1.1.9DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]

Un número de punto fijo "exacto" comprimido.

  • * M* es el número total de dígitos (precisión), su rango es de 1 a 65 y el valor predeterminado es 10.
  • Des el número de dígitos (escala) a la derecha del punto decimal. Va de 0 a 30 y no puede ser mayorM . El valor predeterminado es 0.
  • 小数点Los signos y -signos (negativos) no se cuentan M. Si ** Des 0, el valor no tiene punto ni parte decimal.

DECIMAL 文字文本的长度也有限制;请参阅“表达式处理”。)

如果指定 UNSIGNED,则不允许负值。

所有与 DECIMAL 列的基本计算 ( +, -, *, /) 都以 65 位数字的精度完成。

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

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

1.1.11 FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]

一个小的(单精度)浮点数。允许的值为-3.402823466E+38 to -1.175494351E-3801.175494351E-38 to 3.402823466E+38。这些是基于 IEEE 标准的理论限制。根据硬件或操作系统,实际范围可能会稍小一些。

M是总位数,D是小数点后的位数。如果省略M 和*D*,则将值存储在硬件允许的范围内。单精度浮点数精确到大约 7 位小数。

FLOAT(M,D) 是一个非标准的 MySQL 扩展。

如果指定 UNSIGNED,则不允许负值。

使用FLOAT可能会给您带来一些意想不到的问题,因为 MySQL 中的所有计算都是以双精度完成的。请参见 “解决没有匹配行的问题”

1.1.12 FLOAT(p) [UNSIGNED] [ZEROFILL]

Un número de punto flotante. pRepresenta la precisión en bits, pero MySQL solo usa este valor para determinar si usar FLOATo DOUBLEusar el tipo de datos generado. Si * pes de 0 a 24, el tipo de datos se convierte en FLOATNingunoM * o D** el valor. Si ** pes de 25 a 53, el tipo de datos pasa a ser DOUBLENinguno MoD Valor. El rango de la columna de resultados es el mismo que el de los tipos de datos simples FLOATo dobles DOUBLEdescritos anteriormente en esta sección.

FLOAT(p)Se proporciona sintaxis para compatibilidad con ODBC. `

1.1.13DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]

Un número de coma flotante de tamaño normal (doble precisión). Los valores permitidos son -1.7976931348623157E+308to y to . Estos son límites teóricos basados ​​en los estándares IEEE. Dependiendo de su hardware o sistema operativo, el rango real puede ser ligeramente menor.-2.2250738585072014E-30802.2250738585072014E-3081.7976931348623157E+308

Mes el número total de dígitos y Des el número de dígitos después del punto decimal. SiMD se omiteny **Los números de coma flotante de doble precisión tienen una precisión de aproximadamente 15 decimales.

DOUBLE(M,D)Es una extensión MySQL no estándar.

Si se especifica UNSIGNED, no se permiten valores negativos.

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

1.2 Tipos de enteros (valores exactos): INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT

MySQL admite los tipos de enteros estándar de SQL INTEGER(o INT) y SMALLINT. Como extensión del estándar, MySQL también admite los tipos de enteros TINYINT, MEDIUMINTy BIGINT. La siguiente tabla muestra el espacio de almacenamiento y el rango requerido para cada tipo de entero.

Tabla 1.1 Almacenamiento requerido y rango de tipos de enteros admitidos por MySQL

tipo Almacenamiento (bytes) Valor mínimo (con signo) Valor máximo (con signo) Valor mínimo (sin firmar) Valor máximo (sin firmar)
TINYINT 1 -128 127 0 255
SMALLINT 2 -32768 32767 0 65535
MEDIUMINT 3 -8388608 8388607 0 16777215
INT 4 -2147483648 2147483647 0 4294967295
BIGINT 8 -2[^63] 2[^63]-1 0 2[^64]-1

1.3 Tipos de punto fijo (valores exactos) - DECIMAL, NUMÉRICO

DECIMALy NUMERIClos tipos almacenan valores de datos numéricos exactos. Utilice estos tipos cuando sea importante mantener una precisión precisa, como en el caso de los datos monetarios. En MySQL, NUMERICse implementa como , por lo que también se aplica DECIMALlo siguiente .DECIMALNUMERIC

MySQL DECIMALalmacena valores en formato binario (nota: en lugar de almacenar caracteres numéricos en cadenas, porque al principio pensé que eran cadenas), cada 9 caracteres numéricos se segmenta y almacena en 4 bytes, y los números enteros se almacenan por separado. , Y la parte decimal también se segmenta según cada 9 caracteres numéricos. Para la parte que tiene menos de 9 caracteres después de la segmentación, los dígitos restantes se almacenan según el principio de número mínimo de bytes. Para obtener detalles sobre cómo almacenarlo, consulte "Matemáticas exactas" .

DECIMALLa precisión y la escala se pueden especificar (y normalmente se hacen) en la declaración de la columna . Por ejemplo:

salary DECIMAL(5,2)

En este caso, 5es la precisión y 2el número de decimales. La precisión se expresa como la cantidad de dígitos significativos en los que se almacena el valor y la escala se expresa como la cantidad de dígitos que se pueden almacenar después del punto decimal.

SQL estándar requiere DECIMAL(5,2)la capacidad de almacenar cualquier valor con 5 dígitos y 2 decimales, por lo que salaryel rango de valores que se pueden almacenar en la columna oscila entre -999.99y 999.99.

En SQL estándar, la sintaxis DECIMAL(M)es equivalente a DECIMAL(M,0). De manera similar, la sintaxis DECIMALes equivalente a DECIMAL(M,0), lo que permite a la implementación decidir Mel valor de . MySQL admite estas dos formas diferentes de DECIMALsintaxis. MEl valor predeterminado es 10.

Si el decimal es 0, DECIMALel valor no contiene punto decimal ni parte decimal.

DECIMALEl número máximo de dígitos es 65, pero el rango real de una DECIMALcolumna determinada puede estar limitado por la precisión o escala de la columna determinada. Si un valor asignado a dicha columna tiene más de un número específico de decimales permitidos, el valor se convierte a ese número de decimales. (El comportamiento exacto es específico del sistema operativo, pero normalmente el efecto es truncar al número de bits permitidos).

1.4 Tipos de coma flotante (valores aproximados) - FLOAT, DOUBLE

FLOATy DOUBLElos tipos representan valores de datos numéricos aproximados. MySQL usa cuatro bytes para valores de precisión simple y ocho bytes para valores de precisión doble.

Para FLOAT, el estándar SQL permite palabras clave entre paréntesis para especificar la precisión de los siguientes decimales (pero no el rango de exponentes) en unidades de bits (tenga en cuenta que es diferente de los dígitos de los números de coma fija, aquí hay dígitos binarios), es decir es FLOAT(p). MySQL también admite esta especificación de precisión opcional, pero FLOAT(p)el valor de precisión de solo se usa para determinar el tamaño de almacenamiento, y una precisión de 0 a 23 producirá una FLOATcolumna de precisión simple de 4 bytes. Las precisiones de 24 a 53 producen una columna doble de 8 bytes DOUBLE.

MySQL permite el uso de sintaxis no estándar: FLOAT(M,D)o REAL(M,D)o DOUBLE PRECISION(M,D). Aquí, significa que (M,D)se puede almacenar un total Mde hasta dígitos , de los cuales Dlos dígitos pueden estar después del punto decimal.
Por ejemplo, una columna definida FLOAT(7,4)como tendrá este aspecto: -999.9999. MySQL realiza redondeo al almacenar valores, por lo que si se inserta 999.00009en FLOAT(7,4)la columna, el resultado aproximado es que 999.0001el dígito después del cuarto decimal se redondea y 0,00009 se "redondea" a 0,00010.

Debido a que los valores de coma flotante son aproximados y no se almacenan como valores exactos, intentar tratarlos como valores exactos en las comparaciones puede causar problemas. También se ven afectados por dependencias de plataforma o implementación. Consulte "Problemas con el valor de punto flotante" para obtener más información .

Para una máxima portabilidad, el código que necesita almacenar valores de datos numéricos aproximados debe usar FLOATo DOUBLE PRECISIONno especificar precisión o número de dígitos.

Tipo de valor de 1,5 bits - BIT

BITEl tipo de datos se utiliza para almacenar valores de "bits" (binarios). Un BIT(M)tipo permite el almacenamiento Mde valores de dígitos binarios. MEl rango puede ser de 1 a 64.

Para especificar el valor de un "bit", se puede utilizar la notación binaria b'value'. bIndica que va seguido de un número binario, entre comillas simples, y valuees un valor binario escrito con ceros y unos. Por ejemplo, b'111'y b'10000000'representan decimales 7y respectivamente 128. Consulte "Literal de valor posicional" .

Si Mse asigna un valor de menos de ** bits de longitud a BIT(M)una columna, el valor se rellena a la izquierda con ceros. Por ejemplo, b'101'al asignar el valor de a BIT(6)la columna, dado que 101solo hay 3 dígitos binarios, lo cual es insuficiente para los 6dígitos esperados, el lado izquierdo se rellena con lo suficiente 0para compensar 6los dígitos b'000101'y se almacena en mysql.

Clúster NDB : el tamaño máximo combinado de NDBtodas las columnas utilizadas en una tabla determinada no debe exceder los 4096 bits.BIT

1.6 Atributos de tipo numérico

1.6.1 pulgadas(M)

int(6) El 6 entre paréntesis representa el número máximo de dígitos que se pueden "mostrar", pero es un concepto diferente al "número de bits" almacenados, no tienen relación y no se afectan entre sí.
El tipo int ocupa 4 bytes, 32 bits binarios, el valor máximo es 2,1 mil millones y el número de números completos es 10 dígitos. int(6) significa decirle a la aplicación que muestre un máximo de 6 dígitos. Estos "6 dígitos" comienzan a contar de derecha a izquierda y cuentan hasta el sexto dígito, es decir, unidades, decenas, centenas, miles, diez mil y decenas. .Miles de personas.
Si se admite (6) depende del procesamiento de la aplicación. MySQL solo recomienda mostrar un máximo de 6 dígitos.
Por ejemplo: si el número "1234567" está almacenado en el campo de int(6), MySQL recomienda mostrar 6 dígitos, es decir, "234567" ", pero la aplicación determina el número real de dígitos mostrados. La aplicación puede aceptar la sugerencia de MySQL de mostrar los últimos 6 dígitos, o puede ignorar esta sugerencia y mostrar el número completo de 7 dígitos. El ancho se devolverá a la aplicación junto con el conjunto de resultados
.

1.6.2 SIN FIRMAR

Todos los tipos de números enteros pueden tener un atributo UNSIGNED opcional (no estándar).
Los tipos sin signo se pueden utilizar para permitir solo números no negativos en una columna o cuando necesite un rango más amplio de valores para la columna. Por ejemplo, si una columna es INT UNSIGNED, el tamaño del rango de la columna (el número de números representables) es el mismo, pero sus puntos finales se mueven hacia arriba, desde el 1 bit original para el signo y los 31 bits para el valor a 0. Los bits para el signo (es decir, bit sin signo) y 32 bits representan valores numéricos, y el rango numérico representable cambia de -2147483648 a 2147483647 y de 0 a 4294967295.

Los tipos de punto flotante y punto fijo también pueden ser SIN FIRMAR. Al igual que los tipos enteros, esta propiedad evita que se almacenen valores negativos en la columna. A diferencia de los tipos de números enteros, el límite superior de los valores de las columnas permanece sin cambios.

1.6.3 LLENADO CERO

Si especifica ZEROFILL para una columna numérica, MySQL agrega automáticamente el atributo UNSIGNED.

1.6.4 AUTO_INCREMENTO

Los tipos de datos enteros o de punto flotante pueden tener el atributo AUTO_INCREMENT. Cuando inserta un valor NULL en una columna indexada con AUTO_INCREMENT, la columna se establece en el siguiente valor de secuencia. Normalmente es valor+1, donde valor es el valor máximo de la columna actual de la tabla. (La secuencia AUTO_INCREMENT comienza con 1)

Almacenar 0 en una columna AUTO_INCREMENT tiene el mismo efecto que almacenar NULL, a menos que el modo SQL NO_AUTO_VALUE_ON_ZERO esté habilitado.
Si la columna permite NULL, insertar NULL en la columna no activará el incremento automático, sino que insertará NULL en la columna.
Si se inserta un número entero positivo en la columna, el número entero positivo se utilizará como una nueva secuencia, de modo que el siguiente valor incremental se organizará secuencialmente a partir de la nueva secuencia.

Operación real:

create table tt (
	ID int(2) primary key AUTO_INCREMENT,
	name VARCHAR(1)
);
> OK

insert into tt VALUES (0, 'a'), (3, 'b'), (NULL, 'c');
> Affected rows: 3

select * from tt;
1	a 	# (0, 'a'), 插入id是0,但实际被自动自增为1。因为0与NULL一样都认为是非法的值,这种值遇上 AUTO_INCREMENT 就被认为需要mysql自增得到一个值
3	b 	# (3, 'b'), 指定了3作为id值,实际上3被采纳为ID值了。因为3是一个合法的数值,所以直接采纳,并将 AUTO_INCREMENT 的自增值记录为3,为下次自增做准备
4	c 	# (NULL, 'c'), 插入id是NULL,但实际被自动自增为4。因为上次已经将自增值改为3了,所以本次的自增是3+1=4

AUTO_INCREMENT no admite columnas de valores negativos.

1.7 Manejo fuera de rango y desbordamiento

Cuando MySQL almacena un valor en una columna numérica fuera del rango permitido por el tipo de datos de la columna, los resultados dependen del modo SQL vigente en ese momento:

  • Si el modo SQL estricto está habilitado, MySQL rechaza los valores fuera de rango con un error según los estándares SQL y la inserción falla.

  • Si el modo restringido no está habilitado, MySQL recorta los valores al punto final apropiado del rango de tipos de datos de la columna y almacena el valor resultante.

    Cuando se asigna un valor fuera de rango a una columna entera, MySQL solo almacena el valor en el rango correspondiente al rango del tipo de datos de la columna (esta oración es un bocado, en lenguaje humano: MySQL truncará los bits altos según a los bits binarios y conservar los bits bajos).

    Cuando un valor asignado a una columna de punto flotante o de punto fijo excede el rango representado por la precisión y escala especificadas (o predeterminadas), MySQL almacena solo el valor correspondiente a ese rango. (¿No entiendo muy bien cómo guardarlo?)

Supongamos que una tabla t1tiene esta definición:

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

Cuando el modo SQL estricto está habilitado, se produce un error fuera de rango:

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)

Cuando el modo SQL estricto no está habilitado, aparece una advertencia recortada:

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 |
+------+------+

Cuando el modo SQL estricto no está habilitado, las conversiones de asignación de columnas debidas al recorte se informan como advertencias para declaraciones de varias filas, y ALTER TABLE. En modo estricto, estas declaraciones fallan y algunos o todos los valores no se insertan ni cambian, dependiendo de factores como si la tabla es transaccional. Para obtener más información, consulte Modo SQL del servidor .LOAD DATAUPDATEINSERT

El desbordamiento durante la evaluación de una expresión numérica provoca un error. Por ejemplo, el BIGINTvalor máximo con signo es 9223372036854775807, por lo que la siguiente expresión produce un error:

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

Para que la operación sea exitosa en este caso, convierta el valor a sin signo;

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

Si se produce un desbordamiento depende del rango de los operandos, por lo que otra forma de manejar la expresión anterior es usar aritmética de valores exactos, ya que el DECIMALrango de valores es mayor que los números enteros:

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

La resta entre valores enteros, uno de los cuales es UNSIGNEDde tipo, produce un resultado sin signo de forma predeterminada. Si el resultado es negativo, se producirá un error:

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)'

Si NO_UNSIGNED_SUBTRACTIONel modo SQL está habilitado, el resultado es un número negativo sin error:

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

Si el resultado de dicha operación se utiliza para actualizar UNSIGNEDuna columna de números enteros, el resultado se recortará al valor máximo del tipo de columna, o NO_UNSIGNED_SUBTRACTIONa 0 si está habilitado. Si el modo SQL estricto está habilitado, se produce un error y las columnas permanecen sin cambios.

2. Tipos de datos de fecha y hora (5 tipos)

2.1 Sintaxis del tipo de datos de fecha y hora

2.2 Tipos de FECHA, DATETIME y TIMESTAMP

2.3 tipo de TIEMPO

2.4 Tipo de año

2.5 Limitaciones del AÑO(2) de 2 dígitos y migración al AÑO de 4 dígitos

2.6 Inicialización y actualización automática de TIMESTAMP y DATETIME

2.7 Fracciones de segundo en valores de tiempo

2.8 Conversión entre tipos de fecha y hora

2.9 fecha del año de 2 dígitos

Los tipos de datos de fecha y hora utilizados para representar valores de hora son DATE, TIME, y . Cada tipo de tiempo tiene un rango de valores válidos, así como un valor "cero" que se puede usar cuando especifica un valor no válido que MySQL no puede representar. y los tipos tienen un comportamiento de actualización automática especial, que se describe en la Sección 2.6, “Inicialización y actualización automática de TIMESTAMP y DATETIME” .DATETIMETIMESTAMPYEARTIMESTAMPDATETIME

Para obtener información sobre los requisitos de almacenamiento para tipos de datos temporales, consulte Requisitos de almacenamiento de tipos de datos .

Para obtener una descripción de las funciones que operan con valores de tiempo, consulte Funciones de fecha y hora .

Cuando trabaje con tipos de fecha y hora, tenga en cuenta las siguientes consideraciones generales:

  • MySQL recupera valores de un tipo de fecha u hora determinado en formato de salida estándar, pero intenta interpretar varios formatos para los valores de entrada que usted proporciona (por ejemplo, cuando especifica un valor para asignar o comparar con una fecha o tipo de tiempo). Consulte Literales de fecha y hora para obtener una descripción de los formatos permitidos para los tipos de fecha y hora . Esperando valores válidos de usted. Si utiliza valores en otros formatos, pueden producirse resultados impredecibles.

  • Aunque MySQL intenta interpretar valores en una variedad de formatos, la parte de fecha siempre debe proporcionarse en orden año-mes-día (por ejemplo, '98-09-04') y no en orden mes-día-año o día-mes-año como está. comúnmente utilizado en otros lugares (por ejemplo, Por ejemplo '09-04-98',, '04-09-98'). STR_TO_DATE()Esta función puede resultar útil para convertir cadenas en otro orden al orden año, mes, día .

  • Las fechas que contienen valores de años de 2 dígitos son ambiguas porque se desconoce el siglo. MySQL utiliza las siguientes reglas para interpretar valores de años de 2 dígitos:

    • 70-99Los valores del año en el rango se convierten en 1970-1999.
    • 00-69Los valores del año en el rango se convierten en 2000-2069.

    Consulte también la Sección 2.9, “Años de dos dígitos en fechas” .

  • Convierte un valor de un tipo de hora a otro de acuerdo con las reglas de la Sección 2.8, “Conversiones entre tipos de fecha y hora” .

  • MySQL convierte automáticamente un valor de fecha u hora en un número si el valor se usa en un contexto numérico, y viceversa.

  • De forma predeterminada, cuando MySQL encuentra un valor de un tipo de fecha u hora que está fuera de rango o no es válido para ese tipo, convierte el valor al valor "cero" de ese tipo. La excepción es que los valores fuera de rango TIMEse recortan al TIMErango apropiado.

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

  • MySQL 允许您在 DATE or DATETIME 列中存储日期或月份和日期为零的日期。这对于需要存储您可能不知道确切日期的生日的应用程序很有用。在这种情况下,您只需将日期存储为'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 模式。

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

La siguiente tabla muestra el formato del valor "cero" para cada tipo. Los valores "cero" son especiales, pero puede almacenarlos o hacer referencia a ellos explícitamente utilizando los valores que se muestran en la tabla. También puede utilizar el valor más fácil de escribir '0'o 0representar el valor "cero". El uso de estos valores con tipos de hora que contienen partes de fecha ( DATEy DATETIME) TIMESTAMPpuede generar advertencias o errores. El comportamiento exacto depende de NO_ZERO_DATEqué modo estricto y modo SQL, si los hay, están habilitados; consulte Modo SQL del servidor .

tipo de datos valor "cero"
DATE '0000-00-00'
TIME '00:00:00'
DATETIME '0000-00-00 00:00:00'
TIMESTAMP '0000-00-00 00:00:00'
YEAR 0000

2.1 Sintaxis del tipo de datos de fecha y hora

Los tipos de datos de fecha y hora utilizados para representar valores de hora son DATE, TIME, y .DATETIMETIMESTAMPYEAR

Para las descripciones de rango de DATEy DATETIME, "compatible" significa que, si bien los valores anteriores pueden ser válidos (funcionan), no están garantizados.

MySQL permite fracciones de segundo TIMEy DATETIMEvalores con precisión de hasta microsegundos (6 dígitos). Para definir una columna que contiene fracciones de segundo, utilice la sintaxis ( ), donde es o es TIMESTAMPla type_nameprecisión fspde type_namefracciones TIMEde segundo. Por ejemplo:DATETIMETIMESTAMPfsp

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

El fspvalor **, si se proporciona, debe estar en el rango de 0 a 6. Un valor de 0 significa que no hay parte decimal. Si se omite, la precisión predeterminada es 0. (Esto es diferente del valor predeterminado de SQL estándar de 6 por compatibilidad con versiones anteriores de MySQL).

TIMESTAMPCualquier columna o columna de una tabla DATETIMEpuede tener propiedades de inicialización y actualización automáticas; consulte la Sección 2.6, “Inicialización y actualización automática de TIMESTAMP y DATETIME” .

2.1.1DATE

fecha. El alcance de "compatible" '1000-01-01'es '9999-12-31'. MySQL muestra valores en YYYY-MM-DDformato '' DATE, pero permite el uso de cadenas o números para asignar valores a DATElas columnas.

2.1.2DATETIME[(fsp)]

Combinación de fecha y hora. El alcance de "compatible" '1000-01-01 00:00:00.000000'es '9999-12-31 23:59:59.999999'. MySQL 'YYYY-MM-DD hh:mm:ss[.fraction]'muestra DATETIMEvalores en formato, pero permite asignar valores a DATETIMEcolumnas mediante cadenas o números.

Valores opcionales* fsp*Se puede proporcionar un número en el rango de 0 a 6 para especificar la precisión de fracciones de segundo. Un valor de 0 significa que no hay parte decimal. Si se omite, la precisión predeterminada es 0.

Puede utilizar DEFAULTlas ON UPDATEcláusulas de definición de columnas y para especificar DATETIMEla inicialización y actualización automática de columnas a la fecha y hora actuales, como se describe en la Sección 2.6, “Inicialización y actualización automática de TIMESTAMP y DATETIME” .

2.1.3TIMESTAMP[(fsp)]

marca de tiempo. El rango es '1970-01-01 00:00:01.000000'de UTC a '2038-01-19 03:14:07.999999'UTC. TIMESTAMPEl valor se almacena como el número de segundos desde la época ( '1970-01-01 00:00:00'UTC) TIMESTAMP. Una marca de tiempo no puede representar un valor '1970-01-01 00:00:00', ya que corresponde a 0 segundos de la época, pero el valor 0 está reservado para representar '0000-00-00 00:00:00'este valor "cero".

Valores opcionales* fsp*Se puede proporcionar un número en el rango de 0 a 6 para especificar la precisión de fracciones de segundo. Un valor de 0 significa que no hay parte decimal. Si se omite, la precisión predeterminada es 0.

La forma en que se define el procesamiento del servidor TIMESTAMPdepende del explicit_defaults_for_timestampvalor de una variable del sistema (consulte "Variables del sistema del servidor" ).

  • Si está habilitado, el atributo o explicit_defaults_for_timestampno se asigna automáticamente a ninguna columna. Deben incluirse explícitamente en la definición de la columna. Además, se permite cualquier columna que no esté declarada explícitamente como valor .DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMPTIMESTAMPTIMESTAMPNOT NULLNULL

  • Si explicit_defaults_for_timestampestá deshabilitado, el servidor maneja TIMESTAMPesto de la siguiente manera:
    A menos que se especifique lo contrario, si un valor no se asigna explícitamente a la primera TIMESTAMPcolumna de una tabla, la columna se establece automáticamente en la fecha y hora de modificación más reciente. Esto hace que la columna sea útil TIMESTAMPpara registrar marcas de tiempo de operaciones INSERTOR . UPDATETambién puede establecer una columna con la fecha y hora actuales asignándole un NULLvalor TIMESTAMP, a menos que se haya definido para permitir NULLvalores.

La inicialización y actualización automática a la fecha y hora actuales se pueden especificar mediante las cláusulas de definición de columna DEFAULT CURRENT_TIMESTAMPy . Como se mencionó anteriormente, la primera columna tiene estas propiedades de forma predeterminada. Sin embargo, se puede definir cualquier columna de la tabla para que tenga estas propiedades.ON UPDATE CURRENT_TIMESTAMPTIMESTAMPTIMESTAMP

2.1.4TIME[(fsp)]

tiempo. El rango es '-838:59:59.000000'de '838:59:59.000000'. MySQL muestra valores en formato ' hh:mm:ss[. ]' , pero permite usar cadenas o números para asignar valores a las columnas.fractionTIMETIME

Valores opcionales* fsp*Se puede proporcionar un número en el rango de 0 a 6 para especificar la precisión de fracciones de segundo. Un valor de 0 significa que no hay parte decimal. Si se omite, la precisión predeterminada es 0.

2.1.5YEAR[(4)]

Año en formato de 4 dígitos. MySQL YYYYmuestra YEARvalores en formato, pero permite asignar valores a YEARcolumnas mediante cadenas o números. YEARLos valores se muestran como 1901: 2155o 0000.

Aviso:

Este tipo de datos ha quedado obsoleto y se ha eliminado la compatibilidad en MySQL 5.7.5 YEAR(2). Para convertir una columna de 2 bits YEAR(2)en una columna de 4 bits YEAR, consulte la Sección 2.5, “Limitaciones del AÑO(2) de 2 bits y migración al AÑO de 4 bits” .

Consulte la Sección 2.4, “Tipo de AÑO” para obtener más información sobre YEARel formato de visualización y la interpretación de los valores de entrada .

2.1.6 Notas adicionales sobre valores de tiempo

Funciones de agregación SUM()y AVG()no funcionan con valores de tiempo. (Convierten el valor en un número, perdiendo todo después del primer carácter no numérico). Para solucionar este problema, convierta a unidades numéricas, realice una operación de agregación y luego vuelva a convertir a un valor de tiempo. ejemplo:

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

Aviso:

El servidor MySQL es el mismo MAXDBque con el modo SQL habilitado . Si este modo está habilitado al crear la tabla, las columnas se crean como columnas. Por lo tanto, dichas columnas utilizan el formato de visualización, tienen el mismo rango de valores y no se inicializan ni actualizan automáticamente a la fecha y hora actuales. Consulte Modo SQL del servidor .TIMESTAMPDATETIMETIMESTAMPDATETIMEDATETIME

Obsoleto a partir de MySQL 5.7.22 MAXDB; se eliminará en una versión futura de MySQL.

2.2 Tipos de FECHA, DATETIME y TIMESTAMP

DATEy DATETIMElos TIMESTAMPtipos están relacionados. Esta sección describe sus características, en qué se parecen y en qué se diferencian. MySQL puede reconocer valores en múltiples formatos de y DATEPara obtener más información, consulte "Literales de fecha y hora" . Para las descripciones de rango y , "compatible" significa que, si bien los valores anteriores pueden ser válidos, no están garantizados.DATETIMETIMESTAMPDATEDATETIME

DATEEl tipo se utiliza para valores que tienen una parte de fecha pero no una parte de hora. MySQL 'YYYY-MM-DD'recupera y muestra DATEvalores de tipo en formato. El rango admitido es '1000-01-01'de '9999-12-31'.

DATETIMETipo utilizado para valores que contienen componentes de fecha y hora. MySQL 'YYYY-MM-DD hh:mm:ss'recupera y muestra DATETIMEvalores en formato. El rango admitido es '1000-01-01 00:00:00'de '9999-12-31 23:59:59'.

TIMESTAMPTipo utilizado para valores que contienen componentes de fecha y hora. TIMESTAMPTiene un rango de '1970-01-01 00:00:01'UTC a '2038-01-19 03:14:07'UTC.

Un valor DATETIMEOR TIMESTAMPpuede incluir un componente de fracciones de segundo final con una precisión de hasta microsegundos (6 dígitos). En particular, cualquier parte fraccionaria del valor insertado en DATETIMEla columna o se almacenará en lugar de descartarse. TIMESTAMPDespués de incluir la parte decimal, el formato de estos valores es 'YYYY-MM-DD hh:mm:ss[.fraction]', DATETIMEescriba el rango de valores es '1000-01-01 00:00:00.000000'hasta '9999-12-31 23:59:59.999999', TIMESTAMPescriba el rango de valores es '1970-01-01 00:00:01.000000'hasta '2038-01-19 03:14:07.999999'. La parte fraccionaria siempre debe estar separada del resto del tiempo por un punto decimal; no se reconocen otros separadores de fracciones de segundo. Para obtener información sobre el soporte de fracciones de segundo en MySQL, consulte la Sección 2.7, “Fracciones de segundo en valores de tiempo” .

TIMESTAMPy DATETIMElos tipos de datos proporcionan inicialización y actualización automática a la fecha y hora actuales. Para obtener más información, consulte la Sección 2.6, “Inicialización y actualización automática de TIMESTAMP y DATETIME” .

MySQL TIMESTAMPconvierte valores de la zona horaria actual a UTC para su almacenamiento y luego convierte los valores de UTC a la zona horaria actual para su recuperación. (Esto no sucede con otros tipos, por ejemplo DATETIME, ) De forma predeterminada, la zona horaria actual para cada conexión es la hora del servidor. La zona horaria se puede configurar según la conexión. Siempre que la configuración de la zona horaria permanezca sin cambios, puede devolver el mismo valor almacenado. Si almacena un TIMESTAMPvalor, luego cambia la zona horaria y recupera el valor, el valor recuperado es diferente del valor que almacenó. Esto sucede porque no se utiliza la misma zona horaria para la conversión en ambas direcciones. La zona horaria actual está disponible como time_zonevariable del sistema. Para obtener más información, consulte Compatibilidad con la zona horaria del servidor MySQL . Si el
esquema SQL permite esta conversión, un valor DATEo no válido se convierte en un valor cero ( o ) del tipo correspondiente. El comportamiento exacto depende de si el modo SQL estricto está habilitado y qué modo SQL está habilitado; consulte Modo SQL del servidor .DATETIMETIMESTAMP'0000-00-00''0000-00-00 00:00:00'NO_ZERO_DATE

Tenga en cuenta ciertas propiedades de la interpretación del valor de fecha en MySQL:

  • MySQL permite especificar valores como un formato "relajado" de cadenas, donde cualquier puntuación se puede utilizar como separador entre partes de fecha o partes de hora. Esta sintaxis puede resultar engañosa en algunos casos. Por ejemplo, un valor '10:11:12'puede parecer un valor de tiempo porque se usa :, pero si se usa en un contexto de fecha '2010-11-12'se interpreta como un año. El valor '10:45:15'se convertirá '0000-00-00'porque '45'no es un mes válido.

    El único separador reconocido entre las partes de fecha y hora y la parte de fracciones de segundo es el punto decimal.

  • El servidor requiere que los valores de mes y día sean válidos, no solo en los rangos 1 a 12 y 1 a 31 respectivamente. '2004-04-31'Con el modo estricto deshabilitado, esto se convertirá en una fecha no válida '0000-00-00'y generará una advertencia porque abril no tiene un 31. Cuando el modo estricto está habilitado, las fechas no válidas generarán un error. Para permitir dichas fechas, habilite ALLOW_INVALID_DATESPara obtener más información, consulte Modo SQL del servidor .

  • MySQL no acepta TIMESTAMPvalores que contengan ceros en las columnas de día o mes o que no sean fechas válidas. La única excepción a esta regla es el valor especial "cero" si el modo SQL permite este valor. '0000-00-00 00:00:00'El comportamiento exacto depende de si el modo SQL estricto está habilitado y NO_ZERO_DATEqué modo SQL está habilitado; consulte Modo SQL del servidor .

  • Las fechas que contienen valores de años de 2 dígitos son ambiguas porque se desconoce el siglo. MySQL utiliza las siguientes reglas para interpretar valores de años de 2 dígitos:

    • Los valores del año en el rango 00-69se convierten en 2000-2069.
    • Los valores del año en el rango 70-99se convierten en 1970-1999.

Consulte también la Sección 2.9, “Años de dos dígitos en fechas” .

2.3 tipo de TIEMPO

MySQL recupera y muestra valores en 'hh:mm:ss'formato (o 'hhh:mm:ss'formato para valores grandes de "hora") . Los valores pueden variar de a . La parte de la hora puede ser grande, ya que el tipo se puede utilizar para representar no sólo una hora del día (debe ser inferior a 24 horas) sino también un tiempo transcurrido o un intervalo de tiempo entre dos eventos (que puede ser mucho mayor que 24 horas). , incluso números negativos).TIMETIME'-838:59:59''838:59:59'TIME

MySQL 可以识别TIME几种格式的值,其中一些可以包括一个尾随小数秒部分,精度高达微秒(6 位)。请参阅 “日期和时间文字”。有关 MySQL 中小数秒支持的信息,请参阅 第 2.7 节,“时间值中的小数秒”。特别是,插入到 TIME 列中的值中的任何小数部分都会被存储而不是被丢弃。包含小数部分后, TIME 值的范围为'-838:59:59.000000''838:59:59.000000'

TIME 列分配缩写的时间值时要小心 。MySQL 将带有冒号的时间缩写值解释为一天中的时间。也就是说,'11:12'意味着 '11:12:00',不是 '00:11:12'。MySQL 使用最右边的两个数字表示秒(即,作为经过的时间而不是一天中的时间)的假设来解释不带冒号的缩写值。例如,您可能将 '1112'1112 视为 '11:12:00'(11 点后 12 分钟),但 MySQL 将它们解释为'00:11:12'(11 分钟,12 秒)。同样,'12'12被解释为 '00:00:12'。(个人总结:带冒号的时间值从左到右按“时分秒”的顺序解析,不带冒号的纯数字时间值从右到左按“秒分时”的顺序解析)

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

De forma predeterminada, TIMElos valores fuera del rango que de otro modo serían válidos se recortan al punto final más cercano del rango. Por ejemplo, '-850:00:00'y '850:00:00'se convierte en '-838:59:59'y '838:59:59'. El valor no válido TIMEse convierte a '00:00:00'. Tenga en cuenta que debido a que '00:00:00'es en sí mismo un valor válido TIME, no hay forma de saber a partir del valor almacenado en la tabla '00:00:00'si el valor original se convirtió a no válido o si el valor original fue '00:00:00'.

Para TIMEun manejo más estricto de valores no válidos, habilite el modo SQL estricto para provocar errores. Consulte Modo SQL del servidor .

2.4 Tipo de año

YEAREl tipo es un tipo de 1 byte que se utiliza para representar valores de año . Se puede declarar con YEARun ancho de visualización implícito de 4 caracteres o, de forma equivalente, con un YEAR(4)ancho de visualización explícito.

Aviso

El tipo de datos de 2 bits YEAR(2)está en desuso y su compatibilidad se eliminó en MySQL 5.7.5. Para convertir una columna de 2 bits en una columna YEAR(2)de 4 bits , consulte la Sección 2.5, “Limitaciones del AÑO(2) de 2 bits y migración al AÑO de 4 bits” .YEAR

MySQL YYYYmuestra YEARvalores en el formato que van desde 1901hasta 2155y 0000.

YEARAcepta valores de entrada en múltiples formatos:

  • '1901'Una cadena de 4 dígitos'2155' en el rango de .

  • 1901a un número de 4 dígitos2155 en el rango .

  • '0'Una cadena'99' de 1 o 2 dígitos en el rango hasta . MySQL convierte valores en el rango to en valores en to y valores en el rango to en valores en to .'0''69'20002069YEAR'70''99'19701999YEAR

  • 0a un número de99 1 o 2 dígitos en el rango . MySQL convierte valores en el rango to en valores en to y valores en el rango to en valores en to .16920012069YEAR709919701999YEAR

    Insertar el número 0tiene un valor mostrado de 0000y un valor interno de 0000. Si desea insertar ceros e interpretarlos 2000, especifíquelo como una cadena '0' o '00'.

  • Como YEARresultado de una función que devuelve valores aceptables en el contexto, NOW()p.

Si el modo SQL estricto no está habilitado, MySQL convertirá YEARlos valores no válidos a 0000En el modo SQL estricto, intentar insertar un YEARvalor no válido generará un error.

Consulte también la Sección 2.9, “Años de dos dígitos en fechas” .

2.5 Limitaciones del AÑO(2) de 2 dígitos y migración al AÑO de 4 dígitos

Esta sección describe los problemas que pueden surgir al utilizar YEAR(2)tipos de datos de 2 bits y proporciona YEAR(2)información sobre cómo convertir una columna existente en una columna de valor de año de 4 dígitos, ya sea declarando que tiene un YEARancho de visualización implícito de 4 caracteres o, de manera equivalente, YEAR(4)para visualización explícita. ancho.

Aunque los rangos de valores internos de YEAR/ YEAR(4)y los tipos obsoletos son los mismos ( to y ), el ancho de visualización hace que el tipo sea inherentemente ambiguo porque el valor mostrado indica solo los dos últimos dígitos del valor interno y omite el dígito del siglo. En algunos casos, el resultado puede ser una pérdida de información. Por este motivo, evite utilizar / en su aplicación y utilícelo dondequiera que se espere el tipo de datos del valor del año . A partir de MySQL 5.7.5, se elimina la compatibilidad con columnas de 2 bits existentes y se deben convertir a columnas de 4 bits antes de que puedan utilizarse.YEAR(2)190121550000YEAR(2)YEAR(2)YEARYEAR(4)YEAR(2)YEAR(2)YEAR

2.5.1 YEAR(2)Limitaciones

YEAR(2)Los problemas con los tipos de datos incluyen ambigüedad en los valores mostrados y posible pérdida de información al volcar y recargar valores o convertir a cadenas.

  • El valor mostrado YEAR(2)puede ser ambiguo. Hasta tres YEAR(2)valores con diferentes valores internos pueden tener el mismo valor mostrado, como en el siguiente ejemplo:

    mysql> CREATE TABLE t (y2 YEAR(2), y4 YEAR);
    Query OK, 0 rows affected, 1 warning (0.01 sec)
    
    mysql> INSERT INTO t (y2) VALUES(1912),(2012),(2112);
    Query OK, 3 rows affected (0.00 sec)
    Records: 3  Duplicates: 0  Warnings: 0
    
    mysql> UPDATE t SET y4 = y2;
    Query OK, 3 rows affected (0.00 sec)
    Rows matched: 3  Changed: 3  Warnings: 0
    
    mysql> SELECT * FROM t;
    +------+------+
    | y2   | y4   |
    +------+------+
    |   12 | 1912 |
    |   12 | 2012 |
    |   12 | 2112 |
    +------+------+
    3 rows in set (0.00 sec)
    
  • Si usa mysqldump para volcar la tabla creada en el ejemplo anterior, el archivo de volcado y2usa los mismos 2 bits ( 12) para todos los valores. Si la tabla se vuelve a cargar desde el archivo de volcado, todas las filas generadas tienen un valor interno de 2012y un valor mostrado de 12, por lo que se pierde la distinción entre ellas.

  • Convierte un valor de datos de 2 o 4 dígitos YEARen formato de cadena utilizando su tipo de datos para mostrar el ancho. Supongamos que una YEAR(2)columna y una columna YEAR/ YEAR(4)contienen 1970valores. Luego, cada uno obtendrá los resultados de la cadena de '70'y '1970'. Es decir, la conversión de un valor interno a una cadena pierde información.

  • Al insertar en una columna CSVde una tabla YEAR(2), los valores fuera del rango 1970to 2069se almacenan incorrectamente. Por ejemplo, la inserción 2211daría como resultado un valor mostrado de 11, pero un valor interno de 2011.

YEARPara evitar estos problemas, utilice tipos de datos o de 4 bits en lugar de tipos de datos YEAR(4)de 2 bits . YEAR(2)Las recomendaciones para estrategias de migración aparecen más adelante en esta sección.

(TODO: no completado)

2.6 Inicialización y actualización automática de TIMESTAMP y DATETIME

TIMESTAMPy DATETIMElas columnas se pueden inicializar y actualizar automáticamente a la fecha y hora actuales (es decir, la marca de tiempo actual).

TIMESTAMPPara cualquier columna o de la tabla DATETIME, puede especificar la marca de tiempo actual como valor predeterminado de actualización automática:

  • Las columnas inicializadas automáticamente se configuran con la marca de tiempo actual de las filas insertadas que no tienen un valor asignado a la columna.
  • Una columna actualizada automáticamente se actualiza automáticamente a la marca de tiempo actual cuando el valor de cualquier otra columna en la fila cambia de su valor actual. Si todas las demás columnas se configuran con sus valores actuales, las columnas actualizadas automáticamente permanecen sin cambios. Para evitar que una columna actualizada automáticamente se actualice cuando otras columnas cambian, configúrela explícitamente en su valor actual. Para actualizar una columna actualizada automáticamente si otras columnas no han cambiado, configúrela explícitamente en el valor que debería tener (por ejemplo, configúrelo en CURRENT_TIMESTAMP).

Además, si las variables del sistema están deshabilitadas, puede inicializar o actualizar cualquier columna (pero no ) a la fecha y hora actuales explicit_defaults_for_timestampasignándole un valor , a menos que se haya definido para permitir un valor.TIMESTAMPDATETIMENULLNULL

Para especificar propiedades automáticas, utilice DEFAULT CURRENT_TIMESTAMPlas ON UPDATE CURRENT_TIMESTAMPcláusulas en la definición de columna. No importa el orden de las cláusulas. Si ambos están presentes en la definición de la columna, cualquiera de ellos puede aparecer primero. CURRENT_TIMESTAMPCualquier sinónimo de CURRENT_TIMESTAMPtiene el mismo significado que . Son CURRENT_TIMESTAMP(), NOW(), LOCALTIME, LOCALTIME(), LOCALTIMESTAMP, y LOCALTIMESTAMP().

(TODO: No completado, el resto es la descripción detallada de los valores NULL y los valores predeterminados)

2.7 Fracciones de segundo en valores de tiempo

2.8 Conversión entre tipos de fecha y hora

2.9 fecha del año de 2 dígitos

3. Tipo de datos de cadena

3.1 Sintaxis del tipo de datos de cadena

3.2 tipos CHAR y VARCHAR

3.3 tipos BINARIO y VARBINARIO

3.4 Tipos de BLOB y TEXTO

3.5 tipo ENUM

3.6 tipo de CONJUNTO

3.1 Sintaxis del tipo de datos de cadena

3.2 tipos CHAR y VARCHAR

3.3 tipos BINARIO y VARBINARIO

3.4 Tipos de BLOB y TEXTO

3.5 tipo ENUM

3.6 tipo de CONJUNTO

4. Tipos de datos espaciales

4.1 Tipos de datos espaciales

4.2 Modelo geométrico OpenGIS

4.3 Formatos de datos espaciales admitidos

4.4 Bienformación y validez geométrica

4.5 Crear columnas espaciales

4.6 Llenar columnas espaciales

4.7 Obtención de datos espaciales

4.8 Análisis espacial de optimización

4.9 Crear índice espacial

4.10 Uso de índices espaciales

4.1 Tipos de datos espaciales

4.2 Modelo geométrico OpenGIS

4.3 Formatos de datos espaciales admitidos

4.4 Bienformación y validez geométrica

4.5 Crear columnas espaciales

4.6 Llenar columnas espaciales

4.7 Obtención de datos espaciales

4.8 Análisis espacial de optimización

4.9 Crear índice espacial

4.10 Uso de índices espaciales

5. tipo de datos JSON

5.1. Creación de valores JSON
5.2. Normalización, fusión y empaquetado automático de valores JSON
5.3. Búsqueda y modificación de valores JSON
5.4. Sintaxis de ruta JSON
5.5. Comparación y clasificación de valores JSON
5.6. Conversión entre JSON y Valores no JSON
5.7. Agregación JSON de valores
5.8, referencias relacionadas.

A partir de MySQL 5.7.8, MySQL admite tipos de datos nativos definidos por RFC 7159JSON , que pueden acceder de manera efectiva a datos en documentos JSON (JavaScript Object Notation). Este tipo de datos tiene las siguientes ventajas sobre el almacenamiento de cadenas con formato JSON en una columna de cadena:

  • Valide automáticamente JSONlos documentos JSON almacenados en columnas. Los documentos no válidos generan errores.
  • Formato de almacenamiento optimizado. Los documentos JSON almacenados JSONen columnas se convierten a un formato interno que permite una lectura rápida de los elementos del documento. Cuando el servidor debe leer posteriormente un valor JSON almacenado en este formato binario, no necesita analizar el valor de la representación textual. La estructura del formato binario permite al servidor buscar subobjetos o valores anidados directamente por clave o índice de matriz sin tener que leer todos los valores antes o después de ellos en el documento.

JSONEl espacio necesario para almacenar un documento es aproximadamente el mismo que LONGBLOBo LONGTEXT; consulte la Sección 7, “Requisitos de almacenamiento de tipos de datos” para obtener más detalles . JSONEs importante recordar que el tamaño de cualquier documento JSON almacenado en una columna está limitado por max_allowed_packetel valor de la variable del sistema. (Puede ser mayor que este valor cuando el servidor manipula valores JSON internamente en la memoria; el límite se aplica cuando el servidor lo almacena).

Las columnas JSONno pueden tener NULLvalores no predeterminados.

Además de JSONlos tipos de datos, existe un conjunto de funciones SQL que permiten operaciones con valores JSON, como crear, manipular y buscar. La siguiente discusión muestra ejemplos de estas operaciones. Consulte la Sección 12.18, “Funciones JSON” para obtener detalles sobre funciones individuales .

También se proporciona un conjunto de funciones espaciales para operar con valores GeoJSON. Consulte Funciones espaciales de GeoJSON .

JSONLas columnas, al igual que otras columnas de tipo binario, no se indexan directamente; en su lugar, se crea un índice en la columna generada para JSONextraer un valor escalar de la columna. Para ver un ejemplo detallado, consulte Indexación de columnas generadas para proporcionar índices de columnas JSON.

El optimizador MySQL también busca índices compatibles en columnas virtuales que coincidan con expresiones JSON.

MySQL NDB Cluster 7.5 (7.5.2 y posteriores) admite columnas y funciones MySQL JSON, incluida la creación de índices en columnas JSONgeneradas a partir de columnas como solución alternativa para columnas que no se pueden indexar. Cada tabla admite hasta 3 columnas.JSONJSONNDBJSON

Las siguientes secciones proporcionan información básica sobre la creación y manipulación de valores JSON.

5.1 Crear valor JSON

Una matriz JSON contiene una lista de valores separados por comas y encerrados entre los caracteres [y :]

["abc", 10, null, true, false]

Un objeto JSON contiene un conjunto de pares clave-valor separados por comas y encerrados entre caracteres { comerciales }:

{
    
    "k1": "value", "k2": 10}

Como se muestra en el ejemplo, las matrices y objetos JSON pueden contener valores escalares, es decir, cadenas o números, literales nulos JSON o literales booleanos verdaderos o falsos JSON. Las claves de los objetos JSON deben ser cadenas. También se permiten valores escalares de hora (fecha, hora o fechahora):

["12:18:29.000000", "2015-07-29", "2015-07-29 12:18:29.000000"]

Se permite el anidamiento dentro de elementos de matriz JSON y claves de objetos JSON:

[99, {
    
    "id": "HK500", "cost": 75.99}, ["hot", "cold"]]
{
    
    "k1": "value", "k2": [10, 20]}

También puede obtener valores JSON de las muchas funciones que MySQL proporciona para este propósito (consulte la Sección 12.18.2, “Funciones para crear valores JSON” ) así como convertir valores de otros tipos usándolos CAST(value AS JSON)(consulte Conversión entre JSON) y valor no JSON ) para JSONescribir. Los siguientes párrafos describen cómo MySQL maneja los valores JSON proporcionados como entrada.

En MySQL, los valores JSON se escriben como cadenas. MySQL analiza cualquier cadena utilizada en un contexto que espera un valor JSON y genera un error si no es válido como JSON. Estos contextos incluyen insertar valores en JSONcolumnas con tipos de datos y pasar argumentos a funciones que esperan valores JSON (generalmente mostrados como * json_doco * json_valen la documentación de funciones JSON de MySQL), como se muestra en el siguiente ejemplo:

  • JSONUn intento de insertar el valor en la columna tiene éxito si el valor es un valor JSON válido , pero falla si no lo es:
mysql> CREATE TABLE t1 (jdoc JSON);
Query OK, 0 rows affected (0.20 sec)

mysql> INSERT INTO t1 VALUES('{"key1": "value1", "key2": "value2"}');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO t1 VALUES('[1, 2,');
ERROR 3140 (22032) at line 2: Invalid JSON text: 
"Invalid value." at position 6 in value (or column) '[1, 2,'.

En dichos mensajes de error, Nla posición " en la posición " está basada en 0, pero esto solo debe considerarse una indicación aproximada de en qué parte del valor ocurre realmente el problema.

  • La JSON_TYPE()función espera un parámetro JSON e intenta analizarlo en un valor JSON. Si es válido, se devolverá un valor de tipo JSON; de lo contrario, se generará un error:

    mysql> SELECT JSON_TYPE('["a", "b", 1]');
    +----------------------------+
    | JSON_TYPE('["a", "b", 1]') |
    +----------------------------+
    | ARRAY                      |
    +----------------------------+
    
    mysql> select json_type('{}');
    +-----------------+
    | json_type('{}') |
    +-----------------+
    | OBJECT          |
    +-----------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT JSON_TYPE('"hello"');
    +----------------------+
    | JSON_TYPE('"hello"') |
    +----------------------+
    | STRING               |
    +----------------------+
    
    mysql> SELECT JSON_TYPE('hello');
    ERROR 3146 (22032): Invalid data type for JSON data in argument 1
    to function json_type; a JSON string or JSON type is required.
    

    MySQL utiliza utf8mb4reglas de conjunto de caracteres (juego de caracteres) y utf8mb4_binorden de caracteres (intercalación, reglas de clasificación de caracteres, bin significa usar valores codificados para comparar) para procesar cadenas utilizadas en el contexto JSON. Las cadenas de otros conjuntos de caracteres se convierten utf8mb4según sea necesario. (Para cadenas en asciiel juego de caracteres o utf8, no se requiere conversión porque asciiy utf8es utf8mb4un subconjunto de).

Descripción (agrega la tuya)

colación, reglas de clasificación de caracteres. _binIndica el uso de valores codificados (binario) para comparar, _cilo que indica que no distingue entre mayúsculas y minúsculas (Insensible), _csque indica que no distingue entre mayúsculas y minúsculas

También puede especificar si el valor de la cadena distingue entre mayúsculas y minúsculas, que es diferente de si el nombre de la tabla de MySQL distingue entre mayúsculas y minúsculas.

CREATE TABLE `t` (
  `id` int(11) DEFAULT NULL,
  `s1` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
  `s2` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

# 插入两个数据,一个大写的Sql,一个小写的sql
mysql> insert into t values (NULL,'Sql','Sql'), (NULL,'sql','sql');
Query OK, 2 rows affected (0.04 sec)

# 查询所有数据:只有两条数据
mysql> select * from t;
+----+------+------+
| id | s1   | s2   |
+----+------+------+
|  1 | Sql  | Sql  |
|  2 | sql  | sql  |
+----+------+------+
2 rows in set (0.00 sec)

# 查询 _bin 编码值的字段,这是区分大小写的,所以只能得到小写sql的那一条数据
mysql> select * from t where s1 = 'sql';
+----+------+------+
| id | s1   | s2   |
+----+------+------+
|  2 | sql  | sql  |
+----+------+------+
1 row in set (0.00 sec)

# 查询 _ci 不区分大小写的字段,所以能查询到大写的Sql和小写的sql,共两条数据
mysql> select * from t where s2 = 'sql';
+----+------+------+
| id | s1   | s2   |
+----+------+------+
|  1 | Sql  | Sql  |
|  2 | sql  | sql  |
+----+------+------+
2 rows in set (0.00 sec)

Como alternativa a escribir valores JSON utilizando cadenas literales, existen funciones para combinar valores JSON de elementos componentes. JSON_ARRAY()Acepta una lista de valores (posiblemente vacía) y devuelve una matriz JSON que contiene estos valores:

mysql> SELECT JSON_ARRAY('a', 1, NOW());
+----------------------------------------+
| JSON_ARRAY('a', 1, NOW())              |
+----------------------------------------+
| ["a", 1, "2015-07-27 09:43:47.000000"] |
+----------------------------------------+

JSON_OBJECT()Obtiene una lista (posiblemente vacía) de pares clave-valor y devuelve un objeto JSON que contiene estos pares:

mysql> SELECT JSON_OBJECT('key1', 1, 'key2', 'abc');
+---------------------------------------+
| JSON_OBJECT('key1', 1, 'key2', 'abc') |
+---------------------------------------+
| {
   
   "key1": 1, "key2": "abc"}            |
+---------------------------------------+

JSON_MERGE()Acepta dos o más documentos JSON y devuelve el resultado combinado:

mysql> SELECT JSON_MERGE('["a", 1]', '{"key": "value"}');
+--------------------------------------------+
| JSON_MERGE('["a", 1]', '{"key": "value"}') |
+--------------------------------------------+
| ["a", 1, {
   
   "key": "value"}]                 |
+--------------------------------------------+

Para obtener información sobre la combinación de reglas, consulte Normalización, combinación y ajuste automático de valores JSON .

Los valores JSON se pueden asignar a variables definidas por el usuario:

mysql> SET @j = JSON_OBJECT('key', 'value');
mysql> SELECT @j;
+------------------+
| @j               |
+------------------+
| {
   
   "key": "value"} |
+------------------+

# 以下为我自己的测试。结论:@j的类型是longtext,而不是json类型
mysql> create table test select @j;
Query OK, 1 row affected (0.09 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> desc test;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| @j    | longtext | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
1 row in set (0.03 sec)

Sin embargo, una variable definida por el usuario no puede ser JSONun tipo de datos, por lo que, aunque @jparece un valor JSON en el ejemplo anterior y tiene el mismo juego de caracteres y clasificación que un valor JSON, no tiene un JSONtipo de datos. En cambio, JSON_OBJECT()el resultado se convierte en una cadena cuando se asigna a una variable (de hecho, lo medí para convertirlo a longtexttipo).

La cadena generada al convertir un valor JSON tiene un juego de caracteres utf8mb4y una intercalación utf8mb4_bin:

mysql> SELECT CHARSET(@j), COLLATION(@j);
+-------------+---------------+
| CHARSET(@j) | COLLATION(@j) |
+-------------+---------------+
| utf8mb4     | utf8mb4_bin   |
+-------------+---------------+

Debido utf8mb4_bina que es una intercalación binaria, las comparaciones de valores JSON distinguen entre mayúsculas y minúsculas.

# json字段区分大小写,但普通的字符串字段是不区分大小写
mysql> SELECT JSON_ARRAY('x') = JSON_ARRAY('X'), 'x' = 'X';
+-----------------------------------+-----------+
| JSON_ARRAY('x') = JSON_ARRAY('X') | 'x' = 'X' |
+-----------------------------------+-----------+
|                                 0 |         1 |
+-----------------------------------+-----------+
1 row in set (0.00 sec)

La distinción entre mayúsculas y minúsculas también se aplica a los caracteres JSON y , que siempre deben escribirse en minúsculas null:truefalse

mysql> SELECT JSON_VALID('null'), JSON_VALID('Null'), JSON_VALID('NULL');
+--------------------+--------------------+--------------------+
| JSON_VALID('null') | JSON_VALID('Null') | JSON_VALID('NULL') |
+--------------------+--------------------+--------------------+
|                  1 |                  0 |                  0 |
+--------------------+--------------------+--------------------+

mysql> SELECT CAST('null' AS JSON);
+----------------------+
| CAST('null' AS JSON) |
+----------------------+
| null                 |
+----------------------+
1 row in set (0.00 sec)

mysql> SELECT CAST('NULL' AS JSON);
ERROR 3141 (22032): Invalid JSON text in argument 1 to function cast_as_json:
"Invalid value." at position 0 in 'NULL'.

NULLLa distinción entre mayúsculas y minúsculas de los caracteres JSON difiere de la distinción entre mayúsculas y minúsculas de SQL TRUEy FALSElos caracteres, que pueden estar en cualquier letra:

mysql> SELECT ISNULL(null), ISNULL(Null), ISNULL(NULL);
+--------------+--------------+--------------+
| ISNULL(null) | ISNULL(Null) | ISNULL(NULL) |
+--------------+--------------+--------------+
|            1 |            1 |            1 |
+--------------+--------------+--------------+

A veces puede ser necesario o deseable insertar comillas ( "comillas dobles o simples ') en un documento JSON. Para este ejemplo, supongamos que desea insertar algunos objetos JSON en una tabla creada utilizando las declaraciones SQL que se muestran aquí, que contienen cadenas que representan algunos datos prácticos sobre MySQL, cada una relevante para el par de cadenas de palabras clave adecuado:

mysql> CREATE TABLE facts (sentence JSON);

# 假设要插入json:mascot: The MySQL mascot is a dolphin named "Sakila".
# 使用 MySQL函数 JSON_OBJECT() 将其作为 JSON 对象插入到 facts 表中,必须使用反斜杠转义每个引号字符:
mysql> INSERT INTO facts VALUES
     >   (JSON_OBJECT("mascot", "Our mascot is a dolphin named \"Sakila\"."));

# 如果您将值作为 JSON 对象文字插入,则这不会以相同的方式工作,在这种情况下,您必须使用双反斜杠转义序列,如下所示:
mysql> INSERT INTO facts VALUES
     >   ('{"mascot": "Our mascot is a dolphin named \\"Sakila\\"."}');

# 使用双反斜杠可以防止 MySQL 执行转义序列处理,而是使其将字符串文字传递给存储引擎进行处理。在以刚才显示的任何一种方式插入 JSON 对象后,您可以通过执行简单的 SELECT 来看到反斜杠出现在 JSON 列值中,如下所示:
mysql> SELECT sentence FROM facts;
+---------------------------------------------------------+
| sentence                                                |
+---------------------------------------------------------+
| {
   
   "mascot": "Our mascot is a dolphin named \"Sakila\"."} |
+---------------------------------------------------------+

Para encontrar esta mascotoración específica utilizada como clave, puede usar el operador de ruta de columna ->de la siguiente manera:

mysql> SELECT sentence->"$.mascot" FROM facts;
+---------------------------------------------+
| sentence->"$.mascot"                        |
+---------------------------------------------+
| "Our mascot is a dolphin named \"Sakila\"." |
+---------------------------------------------+
1 row in set (0.00 sec)

Esto deja intacta la barra invertida y las comillas que la rodean. Para mostrar el valor deseado usando como clave mascot, pero sin comillas ni caracteres de escape, use el operador de ruta en línea ->>de la siguiente manera:

mysql> SELECT sentence->>"$.mascot" FROM facts;
+-----------------------------------------+
| sentence->>"$.mascot"                   |
+-----------------------------------------+
| Our mascot is a dolphin named "Sakila". |
+-----------------------------------------+

# 我实测报错:
mysql> SELECT sentence->>"$.mascot" FROM facts;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '>"$.mascot" FROM facts' at line 1

notas

Si el modo SQL del servidor está habilitado NO_BACKSLASH_ESCAPES, el ejemplo anterior no funcionará correctamente. Si se establece este modo, los literales de objetos JSON se pueden insertar usando una barra invertida única en lugar de una barra invertida doble, y las barras invertidas se conservan. Si JSON_OBJECT()utiliza esta función al realizar una inserción y este modo está configurado, debe alternar comillas simples y dobles, de la siguiente manera:

mysql> INSERT INTO facts VALUES
     > (JSON_OBJECT('mascot', 'Our mascot is a dolphin named "Sakila".'));

Para obtener más información sobre el efecto de este modo en los caracteres de escape en valores JSON, consulte JSON_UNQUOTE()la descripción de la función.

5.2 Estandarización, fusión y empaquetado automático de valores JSON

5.2.1 Valores JSON normalizados

Cuando se analiza una cadena y se determina que es un documento JSON válido, también se normaliza: los miembros con claves que son duplicados de claves encontradas previamente en el documento se descartan (incluso si los valores son diferentes). El valor del objeto generado por la siguiente JSON_OBJECT()llamada no incluye el segundo key1elemento porque la clave aparece antes del valor:

mysql> SELECT JSON_OBJECT('key1', 1, 'key2', 'abc', 'key1', 'def');
+------------------------------------------------------+
| JSON_OBJECT('key1', 1, 'key2', 'abc', 'key1', 'def') |
+------------------------------------------------------+
| {
   
   "key1": 1, "key2": "abc"}                           |
+------------------------------------------------------+

Aviso

Este tratamiento de "la primera clave gana" de las claves duplicadas es inconsistente con RFC 7159 . Este es un problema conocido en MySQL 5.7 y se ha solucionado en MySQL 8.0. (Error n.° 86866, Error n.° 26369555)

MySQL también descarta espacios adicionales entre claves, valores o elementos en el documento JSON original y deja (o inserta, si es necesario) un espacio después de cada coma ( ,) o dos puntos ( ) cuando se muestra . :Esto se hace para mejorar la legibilidad.

Las funciones MySQL que producen valores JSON (consulte la Sección 12.18.2, “Funciones que crean valores JSON” ) siempre devuelven valores normalizados.

Para mejorar la eficiencia de la búsqueda, también ordena las claves de los objetos JSON. Debe tener en cuenta que los resultados de esta clasificación están sujetos a cambios y no se garantiza que sean consistentes en todas las versiones .

5.2.2 Fusionar valores JSON

En el contexto de combinar múltiples matrices, varias matrices se combinan en una sola matriz concatenando la matriz nombrada posteriormente al final de la primera matriz . En el siguiente ejemplo, JSON_MERGE()sus parámetros se combinan en una matriz:

mysql> SELECT JSON_MERGE('[1, 2]', '["a", "b"]', '[true, false]');
+-----------------------------------------------------+
| JSON_MERGE('[1, 2]', '["a", "b"]', '[true, false]') |
+-----------------------------------------------------+
| [1, 2, "a", "b", true, false]                       |
+-----------------------------------------------------+

La fusión también se realiza al insertar valores en columnas JSON, como se muestra a continuación:

mysql> CREATE TABLE t1 (c1 JSON);

mysql> INSERT INTO t1 VALUES
     >     ('{"x": 17, "x": "red"}'),
     >     ('{"x": 17, "x": "red", "x": [3, 5, 7]}');

mysql> SELECT c1 FROM t1;
+-----------+
| c1        |
+-----------+
| {
   
   "x": 17} |
| {
   
   "x": 17} |
+-----------+

Cuando se combinan varios objetos, se produce un objeto. Si varios objetos tienen la misma clave, el valor de esa clave en el objeto combinado resultante es una matriz que contiene el valor de la clave:

mysql> SELECT JSON_MERGE('{"a": 1, "b": 2}', '{"c": 3, "a": 4}');
+----------------------------------------------------+
| JSON_MERGE('{"a": 1, "b": 2}', '{"c": 3, "a": 4}') |
+----------------------------------------------------+
| {
   
   "a": [1, 4], "b": 2, "c": 3}                      |
+----------------------------------------------------+

5.2.3 Ajustar automáticamente los valores JSON

  • Ajuste automático de valores que no son de matriz

Los valores que no son de matriz utilizados en contextos que requieren valores de matriz se ajustan automáticamente : el valor está rodeado por [caracteres ]para convertirlo en una matriz. En las siguientes declaraciones, cada argumento se encapsula automáticamente como una matriz ( [1], [2]). Luego combínelos para producir una única matriz resultante:

mysql> SELECT JSON_MERGE('1', '2'); # -> 临时状态: JSON_MERGE([1], [2])
+----------------------+
| JSON_MERGE('1', '2') |
+----------------------+
| [1, 2]               |
+----------------------+
  • Embalaje automático de objetos.

Fusione valores de matriz y objeto envolviendo automáticamente el objeto en una matriz y fusionando las dos matrices:

mysql> SELECT JSON_MERGE('[10, 20]', '{"a": "x", "b": "y"}');
# -> 临时状态:JSON_MERGE('[10, 20]', '[{"a": "x", "b": "y"}]'); 将后面的{} 自动包装为[{}]
+------------------------------------------------+
| JSON_MERGE('[10, 20]', '{"a": "x", "b": "y"}') |
+------------------------------------------------+
| [10, 20, {
   
   "a": "x", "b": "y"}]                 |
+------------------------------------------------+

5.3 Buscar y modificar valores JSON

Las expresiones de ruta JSON seleccionan un valor en un documento JSON.

Las expresiones de ruta son útiles para funciones que extraen parte de un documento JSON o modifican un documento JSON para especificar en qué parte del documento operar. namePor ejemplo, la siguiente consulta extrae el valor de un miembro con una clave de un documento JSON :

mysql> SELECT JSON_EXTRACT('{"id": 14, "name": "Aztalan"}', '$.name');
+---------------------------------------------------------+
| JSON_EXTRACT('{"id": 14, "name": "Aztalan"}', '$.name') |
+---------------------------------------------------------+
| "Aztalan"                                               |
+---------------------------------------------------------+

La sintaxis de la ruta utiliza un $carácter inicial para identificar el documento JSON que se está considerando, seguido de expresiones opcionales después del selector que a su vez especifican partes más específicas del documento:

  • Un punto seguido del nombre de la clave nombra al miembro en el objeto usando la clave dada. Si el nombre sin comillas no es válido en una expresión de ruta (por ejemplo, contiene espacios), el nombre de la clave debe especificarse entre comillas dobles.

  • [N]Inmediatamente después pathsignifica seleccionar un elemento pathcon el subíndice del nombre de la matriz () , que es un número entero que comienza desde cero. Si la selección no es una matriz, * *[0] equivale a :NNpathpathpath

    mysql> SELECT JSON_SET('"x"', '$[0]', 'a');
    +------------------------------+
    | JSON_SET('"x"', '$[0]', 'a') |
    +------------------------------+
    | "a"                          |
    +------------------------------+
    1 row in set (0.00 sec)
    
  • La ruta puede contener caracteres *comodín **:

    • .[*]Calcule los valores de todos los miembros en un objeto JSON.
    • [*]Calcule el valor de todos los elementos en una matriz JSON.
    • prefix**suffixCuenta todas las rutas prefixque comienzan y terminan en .suffix
  • Las rutas que no existen en el documento (evaluadas como datos inexistentes) se evalúan como NULL.

Hagamos $referencia a esta matriz JSON de tres elementos:

[3, {
    
    "a": [5, 6], "b": 10}, [99, 100]]

Entonces:

  • $[0]Evaluado como 3.
  • $[1]Evaluado como {"a": [5, 6], "b": 10}.
  • $[2]Evaluado como [99, 100].
  • $[3]Evalúa hasta NULL(se refiere al cuarto elemento del array, que no existe).

Debido a que $[1]y $[2]evalúan valores no escalares, se pueden usar como base para expresiones de ruta más específicas que seleccionan valores anidados. ejemplo:

  • $[1].aEvaluado como [5, 6].
  • $[1].a[1]Evaluado como 6.
  • $[1].bEvaluado como 10.
  • $[2][0]Evaluado como 99.

Como se mencionó anteriormente, si el nombre de la clave no es válido en una expresión de ruta, los componentes de la ruta de la clave deben estar entre comillas. Hagamos $referencia a este valor:

{
    
    "a fish": "shark", "a bird": "sparrow"}

Ambas claves contienen un espacio y deben estar entre comillas:

  • $."a fish"Evaluado como shark.
  • $."a bird"Evaluado como sparrow.

Una ruta que utiliza comodines se evalúa como una matriz que puede contener varios valores:

mysql> SELECT JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.*');
+---------------------------------------------------------+
| JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.*') |
+---------------------------------------------------------+
| [1, 2, [3, 4, 5]]                                       |
+---------------------------------------------------------+
mysql> SELECT JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.c[*]'); # 与'$.c' 等价
+------------------------------------------------------------+
| JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.c[*]') |
+------------------------------------------------------------+
| [3, 4, 5]                                                  |
+------------------------------------------------------------+

En el siguiente ejemplo, la ruta $**.bse evalúa como múltiples rutas ( $.a.bsuma $.c.b) y produce una matriz de valores de ruta coincidentes:

mysql> SELECT JSON_EXTRACT('{"a": {"b": 1}, "c": {"b": 2}}', '$**.b');
+---------------------------------------------------------+
| JSON_EXTRACT('{"a": {"b": 1}, "c": {"b": 2}}', '$**.b') |
+---------------------------------------------------------+
| [1, 2]                                                  |
+---------------------------------------------------------+

En MySQL 5.7.9 y posteriores, puede utilizar column->pathidentificadores de columna JSON y expresiones de ruta JSON como JSON_EXTRACT(column, path)sinónimos de Para obtener más información, consulte la Sección 12.18.3, “Funciones para buscar valores JSON” . Consulte también Indexar columnas generadas para proporcionar índices de columnas JSON .

Algunas funciones toman un documento JSON existente, lo modifican de alguna manera y devuelven el documento modificado como resultado. Las expresiones de ruta indican dónde se realizan los cambios en el documento. Por ejemplo, JSON_SET()las funciones JSON_INSERT()y JSON_REPLACE()aceptan cada una un documento JSON, más uno o más pares de ruta/valor que describen dónde modificar el documento y los valores a usar. Estas funciones se diferencian en cómo manejan los valores existentes y no existentes en el documento.

Considere este documento:

mysql> SET @j = '["a", {"b": [true, false]}, [10, 20]]';

JSON_SET()Reemplace el valor de una ruta existente y agregue el valor de una ruta que no existe:

mysql> SELECT JSON_SET(@j, '$[1].b[0]', 1, '$[2][2]', 2);
+--------------------------------------------+
| JSON_SET(@j, '$[1].b[0]', 1, '$[2][2]', 2) |
+--------------------------------------------+
| ["a", {
   
   "b": [1, false]}, [10, 20, 2]]      |
+--------------------------------------------+

En este caso, la ruta $[1].b[0]selecciona un valor existente ( true), que se reemplaza por el siguiente valor del parámetro de ruta ( 1). La ruta $[2][2]no existe, por lo que el valor correspondiente ( 2) se agrega a $[2]los valores seleccionados.

JSON_INSERT()Agregue nuevos valores sin reemplazar los valores existentes:

mysql> SELECT JSON_INSERT(@j, '$[1].b[0]', 1, '$[2][2]', 2);
+-----------------------------------------------+
| JSON_INSERT(@j, '$[1].b[0]', 1, '$[2][2]', 2) |
+-----------------------------------------------+
| ["a", {
   
   "b": [true, false]}, [10, 20, 2]]      |
+-----------------------------------------------+
# TODO: 没看明白,为什么 '$[1].b[0]', 1 这个路径/值 对没有被添加到"b"数组的0号下标中

JSON_REPLACE()Reemplace los valores existentes e ignore los nuevos valores:

mysql> SELECT JSON_REPLACE(@j, '$[1].b[0]', 1, '$[2][2]', 2);
+------------------------------------------------+
| JSON_REPLACE(@j, '$[1].b[0]', 1, '$[2][2]', 2) |
+------------------------------------------------+
| ["a", {
   
   "b": [1, false]}, [10, 20]]             |
+------------------------------------------------+

Los pares ruta/valor se evalúan de izquierda a derecha. El documento generado al evaluar un par se convierte en el nuevo valor para evaluar el siguiente par.

JSON_REMOVE()Acepta un documento JSON y una (o más) rutas que especifican los valores que se eliminarán del documento. El valor de retorno es el documento original menos cualquier selección de ruta que exista en el documento:

mysql> SELECT JSON_REMOVE(@j, '$[2]', '$[1].b[1]', '$[1].b[1]');
+---------------------------------------------------+
| JSON_REMOVE(@j, '$[2]', '$[1].b[1]', '$[1].b[1]') |
+---------------------------------------------------+
| ["a", {
   
   "b": [true]}]                              |
+---------------------------------------------------+

Los caminos tienen los siguientes efectos:

  • $[2]Coincide [10, 20]y elimina.
  • El primero $[1].b[1]coincide con bel elemento falsey lo elimina.
  • El segundo $[1].b[1]no coincide con ningún elemento: el elemento que se esperaba que coincidiera se eliminó, la ruta ya no existe y no tiene ningún efecto.

5.4 Sintaxis de ruta JSON

Muchas de las funciones JSON admitidas por MySQL y descritas en otras partes de este manual (consulte la Sección 12.18, “Funciones JSON” ) requieren expresiones de ruta para identificar elementos específicos en un documento JSON. Una ruta consta de una serie de rutas y una o más bifurcaciones de ruta . Para las rutas utilizadas en las funciones JSON de MySQL, el alcance es siempre el documento que se busca o se manipula de otro modo, $representado por el carácter principal. Las ramas de la ruta (tramos de la ruta) están separadas por puntos ( .). Una celda de la matriz está [N]representada por , donde Nes un número entero no negativo. El nombre de la clave debe ser una cadena entre comillas dobles o un identificador ECMAScript válido (consulte http://www.ecma-international.org/ecma-262/5.1/#sec-7.6). Las expresiones de ruta (como el texto JSON) deben codificarse utilizando el juego de caracteres o ascii. Otras codificaciones de caracteres están implícitamente obligadas a . La sintaxis completa es la siguiente:utf8utf8mb4utf8mb4

pathExpression:
    scope[(pathLeg)*]

pathLeg:
    member | arrayLocation | doubleAsterisk

member:
    period ( keyName | asterisk )

arrayLocation:
    leftBracket ( nonNegativeInteger | asterisk ) rightBracket

keyName:
    ESIdentifier | doubleQuotedString

doubleAsterisk:
    '**'

period:
    '.'

asterisk:
    '*'

leftBracket:
    '['

rightBracket:
    ']'

Como se mencionó anteriormente, en MySQL, el alcance de una ruta es siempre el documento en el que se opera, expresado como $Puede '$'usarlo como sinónimo de documento en una expresión de ruta JSON.

notas

Algunas implementaciones admiten referencias de columnas de rango de ruta JSON; actualmente, MySQL no las admite.

Los comodines *y **etiquetas se utilizan de la siguiente manera:

  • .*Representa los valores de todos los miembros del objeto.

  • [*]Representa los valores de todas las celdas de la matriz.

  • [prefix]**suffixRepresenta todas las rutas prefixque comienzan y terminan con . es opcional, pero obligatorio; en otras palabras, la ruta no puede terminar en .suffixprefixsuffix**

    Además, es posible que la ruta no contenga la secuencia ***(3 asteriscos).

JSON_CONTAINS_PATH()Para ver ejemplos de sintaxis de rutas, consulte las descripciones de varias funciones JSON que toman rutas como argumentos , como JSON_SET()y JSON_REPLACE(). Consulte la descripción de la función para ver un ejemplo del uso * de los caracteres comodín y .**JSON_SEARCH()

5.5 Comparación y clasificación de valores JSON

Puede comparar valores JSON utilizando =los operadores , <, , , y .<=>>=<>!=<=>

Los siguientes operadores y funciones de comparación aún no se admiten para valores JSON:

La solución alternativa para los operadores y funciones de comparación que acabamos de enumerar es convertir los valores JSON a tipos de datos de cadena o numéricos nativos de MySQL para que tengan tipos escalares consistentes que no sean JSON.

La comparación de valores JSON se produce en dos niveles. La comparación de primer nivel se basa en el tipo JSON del valor comparado. Si los tipos son diferentes, el resultado de la comparación depende únicamente de qué tipo tiene mayor prioridad. Si dos valores tienen el mismo tipo JSON, se realiza una comparación de segundo nivel utilizando reglas específicas del tipo.

La siguiente lista muestra la prioridad de los tipos JSON, desde la prioridad más alta hasta la más baja. (El nombre del tipo es JSON_TYPE()el nombre devuelto por la función). Los tipos que aparecen juntos en una línea tienen la misma prioridad. Cualquier valor de tipo JSON enumerado anteriormente en la lista es mayor que cualquier valor de tipo JSON enumerado más adelante en la lista.

BLOB
BIT
OPAQUE
DATETIME
TIME
DATE
BOOLEAN
ARRAY
OBJECT
STRING
INTEGER, DOUBLE
NULL

Para valores JSON de la misma precedencia, las reglas de comparación son específicas del tipo:

  • BLOB

    NCompara los primeros bytes de dos valores , donde Nes el número de bytes en el valor más corto. Si los primeros Nbytes de dos valores son iguales, el valor más corto se ordena antes que el valor más largo.

  • BIT

    BLOBMismas reglas que .

  • OPAQUE

    BLOBMismas reglas que . OPAQUEEl tipo es un tipo no clasificado.

  • DATETIME

    Los valores de puntos temporales anteriores se ordenan antes que los valores que representan puntos temporales posteriores. Dos valores son iguales si originalmente provienen de MySQL DATETIMEy TIMESTAMPescriben respectivamente, si representan el mismo momento.

  • TIME

    El menor de los dos valores de tiempo se ordena antes que el mayor.

  • DATE

    Las fechas más antiguas se ordenan antes que las fechas posteriores.

  • ARRAY

    Dos matrices JSON son iguales si tienen la misma longitud y los valores en las posiciones correspondientes de la matriz son iguales.

    Si las matrices no son iguales, su orden lo determina el primer elemento en la posición donde existe la diferencia. Las matrices con valores más pequeños en esa posición se ordenan primero. Si todos los valores de la matriz más corta son iguales a los valores correspondientes en la matriz más larga, la matriz más corta se ordena primero.

    ejemplo:

    [] < ["a"] < ["ab"] < ["ab", "cd", "ef"] < ["ab", "ef"]
    
  • BOOLEAN

    Los caracteres falsos de JSON son más pequeños que los caracteres verdaderos de JSON.

  • OBJETO

    Dos objetos JSON son iguales si tienen el mismo conjunto de claves y cada clave tiene el mismo valor en ambos objetos.

    ejemplo:

    {"a": 1, "b": 2} = {"b": 2, "a": 1}
    

    El orden de dos objetos desiguales no está especificado pero es determinista. (Nota: no entiendo esta frase)

  • STRING

    Las cadenas se ordenan léxicamente en los utf8mb4primeros bytes codificados en las dos cadenas que se comparan , donde es la longitud de la cadena más corta. Si los primeros bytes de dos cadenas son iguales, la cadena más corta se considera más pequeña que la cadena más larga.NNN

    ejemplo:

    "a" < "ab" < "b" < "bc"
    

    Esta clasificación equivale a utilizar utf8mb4_binla intercalación para ordenar cadenas SQL. Debido utf8mb4_bina la intercalación binaria, las comparaciones de valores JSON distinguen entre mayúsculas y minúsculas:

    "A" < "a"
    
  • INTEGER,DOUBLE

    Los valores JSON pueden contener números exactos y aproximados. Consulte la Sección 9.1.2, “Literales numéricos” para obtener una discusión general sobre estos tipos de números .

    Las reglas para comparar tipos numéricos nativos de MySQL se analizan en la Sección 12.3, “Conversiones de tipos en la evaluación de expresiones” , pero las reglas para comparar tipos numéricos en valores JSON son algo diferentes:

    • En las comparaciones entre dos columnas que utilizan MySQL nativo INTy DOUBLEtipos numéricos respectivamente, se sabe que todas las comparaciones involucran números enteros y dobles, por lo que para todas las filas los números enteros se convierten en dobles. Es decir, convertir un número exacto en un número aproximado.

    • Por otro lado, si una consulta compara dos columnas JSON que contienen números, no puede saber de antemano si los números son enteros o dobles. Para proporcionar el comportamiento más consistente en todas las filas, MySQL convierte números aproximados en números exactos. El orden resultante es consistente y no pierde la precisión de los números de valores exactos. Por ejemplo, dados los escalares 9223372036854775805, 9223372036854775806, 9223372036854775807 y 9.223372036854776e18, el orden es el siguiente:

    9223372036854775805 < 9223372036854775806 < 9223372036854775807
    < 9.223372036854776e18 = 9223372036854776000 < 9223372036854776001
    

    Si la comparación JSON utiliza reglas de comparación numéricas que no son JSON, es posible que se produzcan pedidos incoherentes. Las reglas comunes de comparación de números de MySQL producen el siguiente orden:

    • Comparación de números enteros:

      9223372036854775805 < 9223372036854775806 < 9223372036854775807
      

      (indefinido 9.223372036854776e18)

    • Doble comparación:

      9223372036854775805 = 9223372036854775806 = 9223372036854775807 = 9.223372036854776e18
      

Para cualquier NULLcomparación de valores JSON con SQL, el resultado es UNKNOWN.

Para comparaciones de valores JSON y no JSON, los valores no JSON se convierten a JSON de acuerdo con las reglas de la siguiente tabla y luego los valores se comparan como se describió anteriormente.

5.6 Convertir entre valores JSON y no JSON

La siguiente tabla resume las reglas que sigue MySQL al convertir entre valores JSON y otros tipos de valores:

Tabla 11.3 Reglas de conversión JSON

Otros tipos CAST (otros tipos COMO JSON) CAST(JSON COMO otros tipos)
JSON Sin alterar Sin alterar
tipo de carácter utf8 ( utf8mb4, utf8, ascii) La cadena se analiza en un valor JSON. Los valores JSON se serializan en utf8mb4cadenas.
Otros tipos de personajes Otras codificaciones de caracteres se convierten implícitamente a utf8mb4tipos de caracteres y se procesan de acuerdo con el conjunto de caracteres utf8. Los valores JSON se serializan en utf8mb4cadenas y luego se convierten a otras codificaciones de caracteres. Es posible que los resultados no tengan sentido.
NULL Devuelve NULLun valor JSON de tipo. no aplica.
tipo GEO ST_AsGeoJSON()Convierta valores GEO a documentos JSON llamando a . Operación ilegal. Solución: Pase CAST(json_val AS CHAR)el resultado de para pasar ST_GeomFromGeoJSON()el resultado de a ST_GeomFromGeoJSON().
todos los demás tipos Genera un documento JSON que consta de un único valor escalar. Éxito si el documento JSON contiene un único valor escalar del tipo de destino y el valor escalar se puede convertir al tipo de destino. De lo contrario, regrese NULLy genere una advertencia.

Para valores JSON ORDER BYy GROUP BYfunciona según los siguientes principios:

  • Los valores JSON escalares se ordenan utilizando las mismas reglas que en la discusión anterior.
  • Para la ordenación ascendente, los SQL NULLse ordenan antes de todos los valores JSON, incluidos los literales JSON NULL; para la ordenación descendente, los SQL se NULLordenan después de todos los valores JSON, incluidos los literales JSON NULL.
  • La clave de clasificación de un valor JSON está limitada por max_sort_lengthel valor de una variable del sistema, por lo que max_sort_lengthse considera igual si los primeros bytes son iguales (y solo entonces difieren).
  • Actualmente no se admite la clasificación de valores no escalares y aparece una advertencia.

对于排序,将 JSON 标量转换为其他一些本机 MySQL 类型可能是有益的。例如,如果名为 jdoc 的列包含 JSON 对象,其成员由id键和非负值组成,请使用此表达式按id 值排序:

ORDER BY CAST(JSON_EXTRACT(jdoc, '$.id') AS UNSIGNED)

如果碰巧有一个生成的列定义为使用与 ORDER BY 中相同的表达式,MySQL 优化器会识别出这一点并考虑将索引用于查询执行计划。请参阅 第 8.3.10 节,“优化器使用生成的列索引”

5.7、JSON 值的聚合

对于 JSON 值的聚合,SQL NULL 值与其他数据类型一样被忽略。非 NULL 值转换为数值(numeric)类型并进行聚合,除了 MIN()MAX()GROUP_CONCAT()。对于数字标量的 JSON 值,转换为数字应该会产生有意义的结果,尽管(取决于值)可能会发生截断和精度损失。将其他 JSON 值转换为数字(number)可能不会产生有意义的结果。

5.8、相关参考:

第 8.3.10 节,“优化器使用生成的列索引”

第 9.1.2 节,“数字文字”

第 11.7 节,“数据类型存储要求”

第 12.3 节,“表达式求值中的类型转换”

第 12.17.11 节,“空间 GeoJSON 函数”

第 12.18 节,“JSON 函数”

第 12.18.2 节,“创建 JSON 值的函数”

第 12.18.3 节,“搜索 JSON 值的函数”

第 13.1.18.8节,索引生成的列以提供 JSON 列索引

6、数据类型默认值

7、数据类型存储要求

7.1、 InnoDB 表存储要求

7.2 Requisitos de almacenamiento de la tabla NDB

7.3 Requisitos de almacenamiento de tipo digital

7.4 Requisitos de almacenamiento del tipo de fecha y hora

7.5 Requisitos de almacenamiento de tipo cadena

7.6 Requisitos de almacenamiento del tipo de espacio

7.7 Requisitos de almacenamiento JSON

7.8 Referencias relacionadas

Los requisitos de almacenamiento de datos de tablas en disco dependen de varios factores. Los diferentes motores de almacenamiento representan tipos de datos y almacenan datos sin procesar de manera diferente. Los datos de la tabla se pueden comprimir para una columna o una fila completa, lo que complica los cálculos de los requisitos de almacenamiento de la tabla o columna.

A pesar de las diferencias en el diseño del almacenamiento en disco, la API interna de MySQL utilizada para comunicar e intercambiar información sobre las filas de la tabla utiliza estructuras de datos consistentes que funcionan en todos los motores de almacenamiento.

Esta sección incluye orientación e información sobre los requisitos de almacenamiento para cada tipo de datos admitido por MySQL, incluido el formato interno y el tamaño del motor de almacenamiento para los tipos de datos representados mediante tamaños fijos. La información se enumera por categoría o motor de almacenamiento.

La representación interna de la tabla tiene un tamaño de fila máximo de 65.535 bytes, aunque el motor de almacenamiento puede admitir filas más grandes. Este número no incluye BLOBlas columnas OR TEXT, que sólo representan de 9 a 12 bytes de este tamaño. Para BLOBy TEXTdatos, la información se almacena internamente en un área de memoria diferente al búfer de filas. Los diferentes motores de almacenamiento manejan la asignación y el almacenamiento de estos datos de manera diferente, según los métodos que utilizan para manejar el tipo correspondiente. Para obtener más información, consulte el Capítulo 15, Motores de almacenamiento alternativos y la Sección 8.4.7, “Limitaciones en el número de columnas y tamaños de filas de la tabla” .

7.1 Requisitos de almacenamiento de tablas InnoDB

有关 InnoDB 表的存储要求的信息, 请参阅第 14.11 节,“InnoDB 行格式”

7.2、 NDB 表存储要求

(跳过)

7.3、 数字类型存储要求

数据类型 需要存储
TINYINT 1 个字节
SMALLINT 2 个字节
MEDIUMINT 3 个字节
INT, INTEGER 4 个字节
BIGINT 8 个字节
FLOAT(p) 4 个字节( 0 <= p<= 24 ) ,8 个字节( 25 <= p<= 53 )
FLOAT 4 个字节
DOUBLE [PRECISION], REAL 8 个字节
DECIMAL(M,D), NUMERIC(M,D) 变长的; 见以下讨论
BIT(M) 大约 ( M+7)/8 字节

DECIMAL( 和 NUMERIC ) 列的值使用二进制格式表示,该格式将九个十进制(以 10 为基数)数字打包成四个字节。每个值的整数和小数部分的存储分别确定。每个九位数字的倍数需要四个字节,而“剩余” 数字需要四个字节的一部分。下表给出了多余数字所需的存储空间。

剩余数字 字节数
0 0
1, 2 1
3, 4 2
5, 6 3
7, 8 4

7.4、 日期和时间类型存储要求

对于TIMEDATETIMETIMESTAMP列,在 MySQL 5.6.4 之前创建的表所需的存储空间与从 5.6.4 开始创建的表不同。这是由于 5.6.4 中的更改允许这些类型具有小数部分,这需要 0 到 3 个字节。

数据类型 MySQL 5.6.4 之前需要存储 MySQL 5.6.4 所需的存储空间
YEAR 1 个字节 1 个字节
DATE 3 个字节 3 个字节
TIME 3 个字节 3 字节 + 小数秒存储
DATETIME 8 个字节 5 字节 + 小数秒存储
TIMESTAMP 4字节 4 字节 + 小数秒存储

从 MySQL 5.6.4 开始,存储 YEARDATE保持不变。但是, TIMEDATETIMETIMESTAMP的表示方式不同。DATETIME打包的效率更高,非小数部分需要 5 个而不是 8 个字节,并且所有3种表示时间的类型的小数部分只需要 0 到 3 个字节,具体取决于存储值的小数秒精度。

小数秒精度 需要存储
0 0 字节
1, 2 1 个字节
3, 4 2 个字节
5, 6 3 个字节

例如,TIME(0)TIME(2)TIME(4)TIME(6)分别使用 3(3+0)、4(3+1)、5(3+2) 和 6(3+3) 个字节。TIMETIME(0)是等效的并且需要相同的存储空间。

有关时间值的内部表示的详细信息,请参阅 MySQL 内部:重要的算法和结构

7.5、 字符串类型存储要求

在下表中,*M*表示非二进制字符串类型的声明列长度(字符长度)和二进制字符串类型的字节数。 *L*表示给定字符串值以字节为单位的实际长度(字节长度)。

数据类型 需要存储
CHAR(M) 紧凑的 InnoDB 行格式系列优化了可变长度字符集的存储。请参阅 COMPACT 行格式存储特性 。否则,M × w 字节 <= M <= 255,其中 w 是字符集中最大长度字符所需的字节数。
BINARY(M) *M*字节,0 <= M <= 255
VARCHAR(M), VARBINARY(M) L+1 个字节(如果列值需要 0 - 255 个字节),L+2 个字节(如果列值超过 255 个字节)
TINYBLOB, TINYTEXT L+ 1 个字节,其中 L< 2[^8] = 256 B
BLOB, TEXT L+ 2 个字节,其中 L< 2[^16] = 64 KB
MEDIUMBLOB, MEDIUMTEXT L+ 3 个字节,其中 L< 2[^24] = 16 MB
LONGBLOB, LONGTEXT L+ 4 个字节,其中 L< 2[^32] = 4 GB
ENUM('value1','value2',...) 1 或 2 个字节,取决于枚举值的数量(最多 65,535 个值)
SET('value1','value2',...) 1、2、3、4 或 8 个字节,取决于集合成员的数量(最多 64 个成员)

可变长度字符串类型使用长度前缀加数据存储。长度前缀根据数据类型需要一到四个字节,数据值需要 L(字符串的字节长度)。例如,一个 MEDIUMTEXT值的存储需要 *L*字节来存储值加上三个字节来存储值的长度。

要计算用于存储特定 CHARVARCHARTEXT列值的字节数,您必须考虑用于该列的字符集以及该值是否包含多字节字符。特别是,在使用 utf8 Unicode 字符集时,您必须牢记并非所有字符都使用相同的字节数。utf8mb3utf8mb4 字符集每个字符最多分别需要三个和四个字节。有关用于不同类别 utf8mb3utf8mb4 字符的存储细分,请参阅 第 10.9 节,“Unicode 支持”

VARCHAR, VARBINARY, BLOBTEXT类型是变长类型。对于它们的每个,存储要求取决于以下因素:

  • 列值的实际长度
  • 列的最大可能长度
  • 列使用的字符集,因为有些字符集包含多字节字符

例如,一个 VARCHAR(255) 列可以包含最大长度为 255 个字符的字符串。假设该列使用latin1字符集(每个字符一个字节),实际需要的存储是字符串的长度(L),加上一个字节来记录字符串的长度。对于字符串 'abcd',*L*是 4 并且存储要求是 5 个字节。如果同一列改为使用ucs2双字节字符集,则存储要求为 10 个字节: 'abcd' 的长度为 8 个字节,该列需要两个字节来存储长度,因为最大长度大于 255(最多 510字节)。

一个 VARCHARVARBINARY 列中可以存储的最大有效字节数取决于最大行大小 65,535 字节,该最大行大小在所有列之间共享。对于存储多字节字符的 VARCHAR 列,最大有效字符数较少。例如, utf8mb3 的每个字符最多需要三个字节,因此可以将使用 utf8mb3 字符集的 VARCHAR 列声明为最多 21,844 个字符。请参阅 第 8.4.7 节,“表列数和行大小的限制”

InnoDB将长度大于或等于 768 字节的固定长度字段编码为可变长度字段,可以在页外存储。例如, CHAR(255)如果字符集的最大字节长度大于 3,则列可以超过 768 个字节,就像utf8mb4

NDB存储引擎支持可变宽度列 。这意味着 VARCHARNDB Cluster 表中的列需要与任何其他存储引擎相同的存储量,除了这些值是 4 字节对齐的。因此,使用字符集 latin1 存储在 VARCHAR(50)列中的 'abcd' 字符串需要 8 个字节(而不是 MyISAM表中相同列值的 5 个字节)。

(此处省略NDB相关的其他描述)NDB_COLUMN有关详细信息,请参阅 NDB_COLUMN 选项

ENUM 对象的大小由不同枚举值的数量决定。一个字节用于最多包含 255 个可能值的枚举。两个字节用于具有 256 到 65,535 个可能值的枚举。请参阅 第 11.3.5 节,“ENUM 类型”

SET 对象的大小由不同集合成员的数量决定。如果设置大小为*N*,则对象占用 (N+7)/8 字节,四舍五入为 1、2、3、4 或 8 个字节。一个 SET 最多可以有 64 个成员。请参阅 第 11.3.6 节,“SET 类型”

7.6、 空间类型存储要求

MySQL 使用 4 个字节存储空间值以指示 SRID,后跟该值的 WKB 表示。该 LENGTH()函数返回值存储所需的空间(以字节为单位)。

有关空间值的 WKB 和内部存储格式的描述,请参阅第 11.4.3 节,“支持的空间数据格式”

7.7、 JSON 存储要求

通常, JSON 列的存储要求与 LONGBLOBLONGTEXT 列的存储要求大致相同;也就是说,JSON 文档占用的空间与存储在其中一种类型的列中的文档字符串表示所占用的空间大致相同。但是,存储在 JSON 文档中的各个值的二进制编码(包括查找所需的元数据和字典)会产生开销。例如,存储在 JSON 文档中的字符串需要 4 到 10 个字节的额外存储空间,具体取决于字符串的长度以及存储它的对象或数组的大小。

此外,MySQL 对存储在JSON列中的任何 JSON 文档的大小施加了限制,使其不能大于 max_allowed_packet.

7.8、相关参考

第 8.4.7 节,“表列数和行大小的限制”

第 10.9 节,“Unicode 支持”

第 11.3.5 节,“ENUM 类型”

第 11.3.6 节,“SET 类型”

第 14.11 节,“InnoDB 行格式”

第 14.11 节,COMPACT 行格式存储特性

第 15 章,替代存储引擎

MySQL 内部:重要的算法和结构

8、为列选择正确的类型

9、使用来自其他数据库引擎的数据类型

Supongo que te gusta

Origin blog.csdn.net/booynal/article/details/125705927
Recomendado
Clasificación