Tipos de dados MySQL - documentos oficiais - notas de estudo - valores numéricos, data e hora, strings, json

Tipos de dados Mysql - documentos oficiais - notas de estudo

Índice

O MySQL suporta vários tipos de dados SQL : tipos numéricos, tipos de data e hora, tipos de string (caractere e byte), tipos espaciais e JSONtipos de dados. Este capítulo fornece uma visão geral e uma descrição mais detalhada das propriedades de tipo em cada categoria, bem como um resumo dos requisitos de armazenamento de tipo de dados.

As descrições dos tipos de dados usam as seguintes convenções:

  • Para tipos inteiros, * M* representa a largura máxima de exibição. Para tipos de ponto flutuante e ponto fixo, ** Mé o número total de bits que podem ser armazenados (precisão). Para tipos de string, * Mé o comprimento máximo. MO valor máximo permitido de * depende do tipo de dados.

  • * D*Aplicável aos tipos ponto flutuante e ponto fixo, indicando o número de dígitos após a vírgula (número de casas decimais). O valor máximo possível é 30, mas não deve ser superior a M-2.

  • * fsp* Aplica-se aos tipos TIME, DATETIMEe TIMESTAMPe representa a precisão de segundos fracionários; ou seja, o número de segundos fracionários após o ponto decimal. O fspvalor * *, se fornecido, deve estar no intervalo de 0 a 6. Um valor 0 significa que não há parte decimal. Se omitido, a precisão padrão é 0. (Isso é diferente do padrão SQL padrão 6 para compatibilidade com versões anteriores do MySQL.)

  • Colchetes ( [e ]) representam partes opcionais da definição do tipo.

1. Tipo de dados numéricos

1.1 Sintaxe do tipo de dados numérico

1.2 Tipos inteiros (valores exatos) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT

1.3 Tipos de ponto fixo (valores exatos) - DECIMAL, NUMERIC

1.4 Tipos de ponto flutuante (valores aproximados) - FLOAT, DOUBLE

Tipo de valor de 1,5 bits - BIT

1.6 Atributos de tipo numérico

1.7 Tratamento fora de alcance e estouro

MySQL suporta todos os tipos de dados numéricos SQL padrão.
Esses tipos incluem tipos de dados numéricos exatos (INTEGER, SMALLINT, DECIMAL e NUMERIC) e tipos de dados numéricos aproximados (FLOAT, REAL e DOUBLE PRECISION).
A palavra-chave INT é sinônimo de INTEGER,
as palavras-chave DEC e FIXED são sinônimos de DECIMAL,
o MySQL trata DOUBLE como sinônimo de DOUBLE PRECISION (extensão não padrão), o
MySQL também trata REAL como sinônimo de DOUBLE PRECISION (variante não padrão ), a menos que o modo SQL REAL_AS_FLOAT esteja habilitado.

O tipo de dados BIT armazena valores de "bit" e suporta tabelas MyISAM, InnoDB, MEMORY e NDB.

1.1 Sintaxe de tipos de dados numéricos

  • Para tipos de dados inteiros, Mrepresenta a largura máxima de exibição. A largura máxima de exibição é 255. A largura de exibição não tem nada a ver com o intervalo de valores que um tipo pode armazenar. int(M)Exemplo: int(4)Indica que a visualização máxima é de 4 dígitos, nomeadamente unidades, dezenas, centenas e milhares.
  • Para tipos de dados de ponto flutuante e ponto fixo, Mé o número total de dígitos que podem ser armazenados (incluindo a parte decimal). O "bit" aqui não é o mesmo conceito que bit. O "bit" aqui se refere ao número de algarismos do número, ou seja, o algarismo das unidades, dezenas, etc.
    • Ponto fixo: decimal(M[,D])Exemplo: decimal(1)Indica que o mysql armazena apenas números inteiros de 1 dígito
    • Ponto flutuante: float(M[,D])Exemplo: float(1)Indica que o mysql armazena apenas números inteiros de 1 dígito

Se você especificar ZEROFILL para uma coluna numérica, o MySQL adiciona automaticamente o atributo UNSIGNED à coluna.

Os tipos de dados numéricos permitem propriedades UNSIGNED e também SIGNED. Entretanto, esses tipos de dados são assinados por padrão, portanto o atributo SIGNED não tem efeito.

SERIAL DEFAULT VALUE é um alias para NOT NULL AUTO_INCREMENT UNIQUE na definição de uma coluna inteira.

Aviso
Ao usar a subtração entre valores inteiros do tipo UNSIGNED, o resultado não será assinado, a menos que o modo SQL NO_UNSIGNED_SUBTRACTION esteja habilitado.

1.1.1BIT[(M)]

Tipo de valor de bit. MRepresenta o número de dígitos em cada valor, de 1até 64. Se Momitido, o padrão é 1.

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

Um número inteiro muito pequeno, ocupando 1bytes. O intervalo assinado é -2[^7] = -128a 2[^7]-1 = 127. O intervalo não assinado é 02[^8]-1 = 255.
MIndica a largura máxima de exibição

1.1.3 BOOL,BOOLEAN

Esses tipos são TINYINT(1)sinônimos de . É considerado um valor zero . São considerados valores diferentes de zero :

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

No entanto, os valores TRUEe FALSEsão apenas apelidos para 1e 0, respectivamente da seguinte forma:

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

As duas últimas afirmações mostram o resultado de 2diferente de TRUEe FALSEporque 2nem é igual 1nem igual a 0.

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

Um pequeno inteiro, ocupando 2bytes. O intervalo assinado é -2[^15] = -32768a 2[^15]-1 = 32767. O intervalo não assinado é 02[^16]-1 = 65535.

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

Um número inteiro de tamanho médio em 3bytes. O intervalo assinado é -2[^23] = -8388608a 2[^23]-1 = 8388607. O intervalo não assinado é 02[^24]-1 = 16777215.

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

Um número inteiro de tamanho normal, em 4bytes. O intervalo assinado é -2[^31] = -2147483648a 2[^31]-1 = 2147483647. O intervalo não assinado é 02[^32]-1 = 4294967295.

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

Este tipo é INTsinônimo de .

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

Um número inteiro grande, ocupando 8bytes. O intervalo assinado é -2[^63] = -9223372036854775808a 2[^63]-1 = 9223372036854775807. O intervalo não assinado é 02[^64]-1 = 18446744073709551615.

SERIALSim, BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUEaliás.

BIGINTAlgumas coisas que você deve observar sobre colunas :

  • Toda aritmética é feita usando valores BIGINTOR com sinal, portanto você não deve usar números inteiros grandes sem sinal maiores que (63 bits), exceto para funções de bit! Se você fizer isso, alguns dos últimos números do resultado poderão estar errados devido a erros de arredondamento ao converter o valor paraDOUBLE9223372036854775807BIGINTDOUBLE

    O MySQL pode lidar com BIGINTas seguintes situações:

    • Ao usar números inteiros BIGINTpara armazenar grandes valores não assinados em colunas.
    • BIGINTQuando colunas são usadas em MIN(*col_name*) e MAX(*col_name*)
    • Ao usar um operador onde ambos os operandos são inteiros ( +, -, *etc.).
  • BIGINTSempre é possível armazenar valores inteiros exatos usando uma string para atribuí-los a uma coluna. Neste caso, o MySQL realiza uma conversão de string em número que não envolve uma representação dupla intermediária.

  • Os operadores e usam aritmética -quando ambos os operandos são valores inteiros . Isso significa que se você multiplicar dois números inteiros grandes (ou o resultado de uma função que retorna um número inteiro), poderá obter resultados inesperados quando o resultado for maior que .+*BIGINT9223372036854775807

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

Um número de ponto fixo "exato" compactado.

  • * M* é o número total de dígitos (precisão), seu intervalo é de 1 a 65 e o valor padrão é 10.
  • Dé o número de dígitos (escala) à direita da vírgula decimal. Varia de 0 a 30 e não pode ser maiorM . O valor padrão é 0.
  • 小数点Sinais e -sinais (negativos) não são contados M. Se ** Dfor 0, o valor não possui ponto decimal ou parte decimal.

( DECIMALO texto literal também tem comprimento limitado; consulte Tratamento de expressões .)

Se especificado UNSIGNED, valores negativos não serão permitidos.

DECIMALTodos os cálculos básicos com colunas ( +, -, *, /) são feitos com 65 dígitos de precisão.

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

Esses tipos são DECIMALsinônimos de . FIXEDSinônimos estão disponíveis para compatibilidade com outros sistemas de banco de dados.

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

Um pequeno número de ponto flutuante (de precisão única). Os valores permitidos são -3.402823466E+38to -1.175494351E-38e 0to . Estes são limites teóricos baseados nos padrões IEEE. O alcance real pode ser um pouco menor dependendo do hardware ou do sistema operacional.1.175494351E-383.402823466E+38

Mé o número total de dígitos e Dé o número de dígitos após a vírgula. SeM e *D* forem omitidos, o valor será armazenado dentro da faixa permitida pelo hardware. Os números de ponto flutuante de precisão simples têm precisão de aproximadamente 7 casas decimais.

FLOAT(M,D)É uma extensão MySQL não padrão.

Se especificado UNSIGNED, valores negativos não serão permitidos.

O uso FLOATpode causar alguns problemas inesperados porque todos os cálculos no MySQL são feitos com dupla precisão. Consulte "Resolvendo linhas sem correspondência" .

1.1.12FLOAT(p) [UNSIGNED] [ZEROFILL]

Um número de ponto flutuante. pRepresenta a precisão em bits, mas o MySQL usa esse valor apenas para determinar se deve usar FLOATou DOUBLEusar o tipo de dados gerado. Se * pfor de 0 a 24, o tipo de dados se tornará FLOATNenhumM * ou D** o valor. Se ** pfor de 25 a 53, o tipo de dados se tornará DOUBLENenhum MouD Valor. O intervalo da coluna de resultados é igual aos tipos de dados simples FLOATou duplos DOUBLEdescritos anteriormente nesta seção.

FLOAT(p)A sintaxe é fornecida para compatibilidade com ODBC. `

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

Um número de ponto flutuante de tamanho normal (precisão dupla). Os valores permitidos são -1.7976931348623157E+308to -2.2250738585072014E-308e 0to . Estes são limites teóricos baseados nos padrões IEEE. Dependendo do seu hardware ou sistema operacional, o alcance real pode ser um pouco menor.2.2250738585072014E-3081.7976931348623157E+308

Mé o número total de dígitos e Dé o número de dígitos após a vírgula. SeM e *D* forem omitidos, o valor será armazenado dentro da faixa permitida pelo hardware. Os números de ponto flutuante de precisão dupla têm precisão de aproximadamente 15 casas decimais.

DOUBLE(M,D)É uma extensão MySQL não padrão.

Se especificado UNSIGNED, valores negativos não serão permitidos.

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

1.2 Tipos inteiros (valores exatos) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT

O MySQL suporta os tipos inteiros padrão SQL INTEGER(or INT) e SMALLINT. Como uma extensão do padrão, o MySQL também suporta os tipos inteiros TINYINTe . A tabela a seguir mostra o espaço de armazenamento e o intervalo necessários para cada tipo inteiro.MEDIUMINTBIGINT

Tabela 1.1 Armazenamento necessário e intervalo de tipos inteiros suportados pelo MySQL

tipo Armazenamento (bytes) Valor mínimo (assinado) Valor máximo (assinado) Valor mínimo (não assinado) Valor máximo (não assinado)
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 ponto fixo (valores exatos) - DECIMAL, NUMERIC

DECIMALe NUMERICos tipos armazenam valores de dados numéricos exatos. Use esses tipos quando for importante manter a precisão precisa, como dados monetários. No MySQL, NUMERICé implementado como DECIMAL, portanto o seguinte DECIMALtambém se aplica NUMERIC.

O MySQL DECIMALarmazena valores em formato binário (nota: em vez de armazenar caracteres numéricos em strings, porque a princípio pensei que fossem strings), cada 9 caracteres numéricos são segmentados e armazenados em 4 bytes, e os inteiros são A parte decimal é armazenada separadamente , e a parte decimal também é segmentada de acordo com cada 9 caracteres numéricos. Para a parte com menos de 9 caracteres após a segmentação, os dígitos restantes são armazenados de acordo com o princípio do número mínimo de bytes. Para obter detalhes sobre como armazená-lo, consulte "Matemática Exata" .

DECIMALA precisão e a escala podem (e geralmente são) especificadas na declaração da coluna . Por exemplo:

salary DECIMAL(5,2)

Neste caso, 5é a precisão e 2é o número de casas decimais. A precisão é expressa como o número de dígitos significativos em que o valor é armazenado, e a escala é expressa como o número de dígitos que podem ser armazenados após o ponto decimal.

O SQL padrão exige DECIMAL(5,2)a capacidade de armazenar qualquer valor com 5 dígitos e 2 casas decimais, portanto salaryo intervalo de valores que podem ser armazenados na coluna varia de -999.99a 999.99.

No SQL padrão, a sintaxe DECIMAL(M)é equivalente a DECIMAL(M,0). Da mesma forma, a sintaxe DECIMALé equivalente a DECIMAL(M,0), o que permite à implementação decidir Mo valor de. MySQL suporta essas duas formas diferentes de DECIMALsintaxe. MO valor padrão é 10.

Se o decimal for 0, DECIMALo valor não contém ponto decimal ou parte decimal.

DECIMALO número máximo de dígitos é 65, mas o intervalo real de uma determinada DECIMALcoluna pode ser limitado pela precisão ou escala da determinada coluna. Se um valor atribuído a essa coluna tiver mais do que um número específico de casas decimais permitido, o valor será convertido para esse número de casas decimais. (O comportamento exato é específico do sistema operacional, mas geralmente o efeito é truncar o número de bits permitidos.)

1.4 Tipos de ponto flutuante (valores aproximados) - FLOAT, DOUBLE

FLOATe DOUBLEos tipos representam valores de dados numéricos aproximados. O MySQL usa quatro bytes para valores de precisão simples e oito bytes para valores de precisão dupla.

Para FLOAT, o padrão SQL permite palavras-chave entre parênteses para especificar a precisão dos seguintes decimais (mas não o intervalo de expoentes) em unidades de bits (observe que é diferente dos dígitos dos números de ponto fixo, aqui são dígitos binários), que é FLOAT(p). O MySQL também suporta esta especificação de precisão opcional, mas FLOAT(p)o valor de precisão de é usado apenas para determinar o tamanho do armazenamento, e uma precisão de 0 a 23 produzirá uma FLOATcoluna de precisão única de 4 bytes. Precisões de 24 a 53 produzem uma coluna dupla de 8 bytes DOUBLE.

MySQL permite o uso de sintaxe não padrão: FLOAT(M,D)or REAL(M,D)or DOUBLE PRECISION(M,D). Aqui, (M,D)significa que um total de até Mdígitos pode ser armazenado, dos quais Dos dígitos podem estar após a vírgula decimal.
Por exemplo, uma coluna definida FLOAT(7,4)como terá a seguinte aparência: -999.9999. O MySQL realiza arredondamento ao armazenar valores, portanto se inserido 999.00009na FLOAT(7,4)coluna, o resultado aproximado é que 999.0001o dígito após a 4ª casa decimal é arredondado, e 0,00009 é "arredondado" para 0,00010.

Como os valores de ponto flutuante são aproximados e não armazenados como valores exatos, tentar tratá-los como valores exatos em comparações pode causar problemas. Eles também são afetados por dependências de plataforma ou implementação. Consulte "Problemas de valor de ponto flutuante" para obter mais informações .

Para máxima portabilidade, o código que precisa armazenar valores aproximados de dados numéricos deve usar FLOATou DOUBLE PRECISIONnão especificar precisão ou número de dígitos.

Tipo de valor de 1,5 bits - BIT

BITO tipo de dados é usado para armazenar valores de "bits" (binários). Um BIT(M)tipo permite o armazenamento Mde valores de dígitos binários. MO intervalo pode ser de 1 a 64.

Para especificar o valor de um "bit", pode-se usar a notação binária b'value'. bIndica que é seguido por um número binário, entre aspas simples, e valueé um valor binário escrito usando 0s e 1s. Por exemplo, b'111'e b'10000000'representam decimal 7e respectivamente 128. Consulte "Literal de valor posicional" .

Se um Mvalor menor que ** bits for atribuído a BIT(M)uma coluna, o valor será preenchido à esquerda com zeros. Por exemplo, b'101'atribua o valor de BIT(6)à coluna. Como 101existem apenas 3 dígitos binários, o que é insuficiente para os 6dígitos esperados, o preenchimento esquerdo é suficiente 0para compensar 6os dígitos e o número b'000101'é armazenado no mysql.

Cluster NDB : O tamanho máximo combinado de NDBtodas as colunas usadas em uma determinada tabela não deve exceder 4.096 bits.BIT

1.6 Atributos de tipo numérico

1.6.1 int(M)

int(6) O 6 entre colchetes representa o número máximo de dígitos que podem ser "exibidos", mas é um conceito diferente do "número de bits" armazenados. Eles não têm relação e não afetam um ao outro.
O tipo int ocupa 4 bytes, 32 bits binários, o valor máximo é 2,1 bilhões e o número de números completos é de 10 dígitos. int(6) significa dizer ao aplicativo para exibir no máximo 6 dígitos. Esses "6 dígitos" começam a contar da direita para a esquerda e contam até o 6º dígito, ou seja, unidades, dezenas, centenas, milhares, dez mil e dezenas ... Milhares de pessoas.
Se (6) é suportado depende do processamento da aplicação. O MySQL recomenda apenas exibir um máximo de 6 dígitos.
Por exemplo: se o número "1234567" estiver armazenado no campo de int(6), o MySQL recomenda exibir 6 dígitos, isto é, "234567" ", mas o número real de dígitos exibidos é determinado pelo aplicativo. O aplicativo pode aceitar a sugestão do MySQL para exibir os últimos 6 dígitos ou pode ignorar esta sugestão e exibir o número completo de 7 dígitos. Este width será retornado ao aplicativo junto com o conjunto de resultados
.

1.6.2 NÃO ASSINADO

Todos os tipos inteiros podem ter um atributo UNSIGNED opcional (não padrão).
Os tipos não assinados podem ser usados ​​para permitir apenas números não negativos em uma coluna ou quando você precisar de um intervalo maior de valores para a coluna. Por exemplo, se uma coluna for INT UNSIGNED, o tamanho do intervalo da coluna (o número de números representáveis) é o mesmo, mas seus pontos finais são movidos para cima, do original 1 bit para o sinal e 31 bits para o valor até 0 bits para o sinal (ou seja, bit não assinado) e 32 bits representam valores numéricos, e o intervalo numérico representável muda de -2147483648 a 2147483647 para de 0 a 4294967295.

Os tipos de ponto flutuante e de ponto fixo também podem ser UNSIGNED. Assim como os tipos inteiros, esta propriedade evita que valores negativos sejam armazenados na coluna. Ao contrário dos tipos inteiros, o limite superior dos valores das colunas permanece inalterado.

1.6.3 PREENCHIMENTO ZERO

Se você especificar ZEROFILL para uma coluna numérica, o MySQL adiciona automaticamente o atributo UNSIGNED.

1.6.4 AUTO_INCREMENTO

Os tipos de dados inteiros ou de ponto flutuante podem ter o atributo AUTO_INCREMENT. Quando você insere um valor NULL em uma coluna indexada com AUTO_INCREMENT, a coluna é definida para o próximo valor de sequência. Normalmente é valor+1, onde valor é o valor máximo da coluna atual na tabela. (A sequência AUTO_INCREMENT começa com 1)

Armazenar 0 em uma coluna AUTO_INCREMENT tem o mesmo efeito que armazenar NULL, a menos que o modo SQL NO_AUTO_VALUE_ON_ZERO esteja habilitado.
Se a coluna permitir NULL, inserir NULL na coluna não acionará o incremento automático, mas inserirá NULL na coluna.
Se um número inteiro positivo for inserido na coluna, o número inteiro positivo será usado como uma nova sequência, de modo que o próximo valor incremental será organizado sequencialmente a partir da nova sequência.

Operação 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 não oferece suporte a colunas de valores negativos.

1.7 Tratamento fora de alcance e estouro

Quando o MySQL armazena um valor em uma coluna numérica fora do intervalo permitido pelo tipo de dados da coluna, os resultados dependem do modo SQL em vigor no momento:

  • Se o modo SQL estrito estiver habilitado, o MySQL rejeitará valores fora do intervalo com um erro de acordo com os padrões SQL e a inserção falhará.

  • Se o modo restrito não estiver habilitado, o MySQL recorta os valores no ponto final apropriado do intervalo de tipos de dados da coluna e armazena o valor resultante.

    Quando um valor fora do intervalo é atribuído a uma coluna inteira, o MySQL armazena apenas o valor no intervalo correspondente ao intervalo do tipo de dados da coluna (esta frase é um bocado, em linguagem humana: o MySQL truncará os bits altos de acordo aos bits binários e retém os bits baixos).

    Quando um valor atribuído a uma coluna de ponto flutuante ou de ponto fixo excede o intervalo representado pela precisão e escala especificada (ou padrão), o MySQL armazena apenas o valor correspondente a esse intervalo. (Não entendo muito bem como salvá-lo?)

Suponha que uma tabela t1tenha esta definição:

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

Quando o modo SQL estrito está ativado, ocorre um erro fora do intervalo:

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)

Quando o modo SQL estrito não está ativado, um aviso recortado aparece:

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

Quando o modo SQL estrito não está habilitado, as conversões de alocação de coluna devido ao recorte são relatadas como avisos para instruções ALTER TABLE, LOAD DATAe UPDATEde múltiplas linhas . No modo estrito, essas instruções falham e alguns ou todos os valores não são inseridos ou alterados, dependendo de fatores como se a tabela é transacional. Para obter mais informações, consulte Modo SQL do Servidor .INSERT

O estouro durante a avaliação de uma expressão numérica causa um erro. Por exemplo, o BIGINTvalor máximo assinado é 9223372036854775807, portanto a seguinte expressão produz um erro:

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

Para que a operação seja bem-sucedida neste caso, converta o valor em unsigned;

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

A ocorrência de overflow depende do intervalo dos operandos, portanto, outra maneira de lidar com a expressão acima é usar a aritmética de valores exatos, uma vez que o DECIMALintervalo de valores é maior que os números inteiros:

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

A subtração entre valores inteiros, um dos quais é UNSIGNEDdo tipo, produz um resultado sem sinal por padrão. Se o resultado for negativo, ocorrerá um erro:

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

Se NO_UNSIGNED_SUBTRACTIONo modo SQL estiver ativado, o resultado será um número negativo sem erro:

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

Se o resultado de tal operação for usado para atualizar UNSIGNEDuma coluna inteira, o resultado será reduzido para o valor máximo do tipo de coluna ou NO_UNSIGNED_SUBTRACTIONpara 0, se habilitado. Se o modo SQL estrito estiver ativado, ocorrerá um erro e as colunas permanecerão inalteradas.

2. Tipos de dados de data e hora (5 tipos)

2.1 Sintaxe do tipo de dados de data e hora

2.2 Tipos DATE, DATETIME e TIMESTAMP

2.3 Tipo de TEMPO

Tipo de 2,4 anos

2.5 Limitações de ANO(2) de 2 dígitos e migração para ANO de 4 dígitos

2.6 Inicialização e atualização automática de TIMESTAMP e DATETIME

2.7 Segundos fracionários em valores de tempo

2.8 Conversão entre tipos de data e hora

2.9 Data do ano com 2 dígitos

Os tipos de dados de data e hora usados ​​para representar valores de hora são DATE, TIME, e . Cada tipo de tempo possui um intervalo de valores válidos, bem como um valor "zero" que pode ser usado quando você especifica um valor inválido que o MySQL não pode representar. e tipos possuem comportamento especial de atualização automática, descrito na Seção 2.6, “Inicialização e atualização automática de TIMESTAMP e DATETIME” .DATETIMETIMESTAMPYEARTIMESTAMPDATETIME

Para obter informações sobre requisitos de armazenamento para tipos de dados temporários, consulte Requisitos de armazenamento de tipos de dados .

Para obter uma descrição de funções que operam em valores de hora, consulte Funções de data e hora .

Ao trabalhar com tipos de data e hora, tenha em mente as seguintes considerações gerais:

  • O MySQL recupera valores de um determinado tipo de data ou hora no formato de saída padrão, mas tenta interpretar vários formatos para os valores de entrada que você fornece (por exemplo, quando você especifica um valor para atribuir ou comparar com uma data ou tipo de tempo). Consulte Literais de data e hora para obter uma descrição dos formatos permitidos para tipos de data e hora . Esperando valores válidos de você. Se você usar valores em outros formatos, poderão ocorrer resultados imprevisíveis.

  • Embora o MySQL tente interpretar valores em vários formatos, a parte da data deve sempre ser fornecida na ordem ano-mês-dia (por exemplo, '98-09-04') e não na ordem mês-dia-ano ou dia-mês-ano como é comumente usado em outro lugar (por exemplo, Por exemplo '09-04-98', ,, '04-09-98'). STR_TO_DATE()Esta função pode ser útil para converter strings em outra ordem para a ordem ano mês dia .

  • As datas que contêm valores de ano de 2 dígitos são ambíguas porque o século é desconhecido. O MySQL usa as seguintes regras para interpretar valores de ano de 2 dígitos:

    • 70-99Os valores do ano no intervalo tornam-se 1970-1999.
    • 00-69Os valores do ano no intervalo tornam-se 2000-2069.

    Consulte também a Seção 2.9, “Anos com dois dígitos em datas” .

  • Converte um valor de um tipo de hora para outro de acordo com as regras da Seção 2.8, “Conversões entre tipos de data e hora” .

  • O MySQL converte automaticamente um valor de data ou hora em um número se o valor for usado em um contexto numérico e vice-versa.

  • Por padrão, quando o MySQL encontra um valor de um tipo de data ou hora que está fora do intervalo ou é inválido para esse tipo, ele converte o valor para o valor "zero" desse tipo. A exceção é que os valores fora do intervalo TIMEsão cortados no TIMEintervalo apropriado.

  • Ao definir o modo SQL com o valor apropriado, você pode especificar com mais precisão os tipos de data que deseja que o MySQL suporte. (Veja "Modo SQL do Servidor".ALLOW_INVALID_DATES ) Você pode fazer com que o MySQL aceite certas datas ativando o modo SQL, por exemplo '2009-11-31'. Isso é útil quando você deseja armazenar valores "possivelmente errados" especificados pelo usuário em um banco de dados (por exemplo, em um formulário da Web) para processamento futuro. Neste modo, o MySQL apenas verifica se o mês está no intervalo de 1 a 12 e o dia está no intervalo de 1 a 31.

  • MySQL permite armazenar dia ou mês e dia com zero na coluna DATEou . DATETIMEIsso é útil para aplicativos que precisam armazenar aniversários cuja data exata talvez você não saiba. Neste caso, você apenas armazena a data como '2009-00-00'ou '2009-01-00'. Entretanto, você não deve esperar resultados corretos para essas datas, como as funções DATE_SUB()ou DATE_ADD()que exigem uma data completa. Para suprimir a parte zero do mês ou do dia da data, ative este NO_ZERO_IN_DATEmodo.

  • O MySQL permite armazenar '0000-00-00'valores "zero" como "datas fictícias". Em alguns casos, isso é NULLmais conveniente do que usar valores e usa menos dados e espaço de índice. Para desabilitar '0000-00-00', habilite este NO_ZERO_DATEmodo.

  • Os valores de data ou hora "zero" usados ​​por meio do Connector/ODBC são convertidos automaticamente NULLporque o ODBC não consegue lidar com esses valores.

A tabela a seguir mostra o formato do valor “zero” para cada tipo. Os valores “zero” são especiais, mas você pode armazená-los ou referenciá-los explicitamente usando os valores mostrados na tabela. Você também pode usar o valor mais fácil de escrever '0'ou 0representar o valor “zero”. Usar esses valores com tipos de hora que contêm partes de data ( DATE, DATETIMEe TIMESTAMP) pode produzir avisos ou erros. O comportamento exato depende de NO_ZERO_DATEqual modo estrito e modo SQL estão ativados, se houver; consulte Modo SQL do Servidor .

tipo de dados valor "zero"
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 Sintaxe do tipo de dados de data e hora

Os tipos de dados de data e hora usados ​​para representar valores de hora são DATE, TIME, e .DATETIMETIMESTAMPYEAR

Para descrições de intervalo de DATEe DATETIME, "suportado" significa que, embora os valores anteriores possam ser válidos (funcionar), eles não são garantidos.

O MySQL permite segundos fracionários TIMEe DATETIMEvalores com precisão de até microssegundos (6 dígitos). TIMESTAMPPara definir uma coluna que contém segundos fracionários, use a sintaxe type_name( fsp), onde type_nameis TIME, DATETIMEou TIMESTAMP, fspé a precisão dos segundos fracionários. Por exemplo:

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

O fspvalor * *, se fornecido, deve estar no intervalo de 0 a 6. Um valor 0 significa que não há parte decimal. Se omitido, a precisão padrão é 0. (Isso é diferente do padrão SQL padrão 6 para compatibilidade com versões anteriores do MySQL.)

TIMESTAMPQualquer coluna ou coluna em uma tabela DATETIMEpode ter propriedades de inicialização e atualização automática; veja Seção 2.6, “Inicialização e atualização automática de TIMESTAMP e DATETIME” .

2.1.1DATE

data. O escopo de "suportado" '1000-01-01'é '9999-12-31'. O MySQL exibe valores no YYYY-MM-DDformato '' DATE, mas permite o uso de strings ou números para atribuir valores às DATEcolunas.

2.1.2DATETIME[(fsp)]

Combinação de data e hora. O escopo de "suportado" '1000-01-01 00:00:00.000000'é '9999-12-31 23:59:59.999999'. O MySQL 'YYYY-MM-DD hh:mm:ss[.fraction]'exibe DATETIMEvalores em formato, mas permite que valores sejam atribuídos a DATETIMEcolunas usando strings ou números.

Valores opcionais* fsp*Um número no intervalo de 0 a 6 pode ser fornecido para especificar a precisão dos segundos fracionários. Um valor 0 significa que não há parte decimal. Se omitido, a precisão padrão é 0.

Você pode usar DEFAULTas ON UPDATEcláusulas de definição de coluna e para especificar DATETIMEa inicialização e atualização automática de colunas para a data e hora atuais, conforme descrito na Seção 2.6, “Inicialização e atualização automática de TIMESTAMP e DATETIME” .

2.1.3TIMESTAMP[(fsp)]

carimbo de data/hora. O intervalo é '1970-01-01 00:00:01.000000'de UTC a '2038-01-19 03:14:07.999999'UTC. TIMESTAMPO valor é armazenado como o número de segundos desde a época ( '1970-01-01 00:00:00'UTC) TIMESTAMP. Um timestamp não pode representar um valor '1970-01-01 00:00:00', pois corresponde a 0 segundos da época, mas o valor 0 é reservado para representar '0000-00-00 00:00:00'esse valor "zero".

Valores opcionais* fsp*Um número no intervalo de 0 a 6 pode ser fornecido para especificar a precisão dos segundos fracionários. Um valor 0 significa que não há parte decimal. Se omitido, a precisão padrão é 0.

A forma como o processamento do servidor TIMESTAMPé definido depende do explicit_defaults_for_timestampvalor de uma variável do sistema (consulte "Variáveis ​​do sistema do servidor" ).

  • Se ativado, o atributo ou explicit_defaults_for_timestampnão será atribuído automaticamente a nenhuma coluna. Eles devem ser incluídos explicitamente na definição da coluna. Além disso, qualquer coluna que não seja explicitamente declarada como valor é permitida .DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMPTIMESTAMPTIMESTAMPNOT NULLNULL

  • Se explicit_defaults_for_timestampdesativado, o servidor tratará TIMESTAMPisso da seguinte maneira:
    A menos que especificado de outra forma, se um valor não for explicitamente atribuído à primeira TIMESTAMPcoluna de uma Tabela, a coluna será automaticamente definida para a data e hora modificadas mais recentemente. Isso torna a coluna útil TIMESTAMPpara registrar carimbos de data/hora de operações INSERTOR . UPDATEVocê também pode definir uma coluna para a data e hora atuais atribuindo-lhe um NULLvalor TIMESTAMP, a menos que tenha sido definido para permitir NULLvalores.

A inicialização e atualização automáticas para a data e hora atuais podem ser especificadas usando as cláusulas de definição de coluna DEFAULT CURRENT_TIMESTAMPe . Conforme mencionado anteriormente, a primeira coluna possui essas propriedades por padrão. No entanto, qualquer coluna da tabela pode ser definida para ter essas propriedades.ON UPDATE CURRENT_TIMESTAMPTIMESTAMPTIMESTAMP

2.1.4TIME[(fsp)]

tempo. O intervalo é '-838:59:59.000000'até '838:59:59.000000'. O MySQL exibe valores no formato ' hh:mm:ss[. ]' , mas permite usar strings ou números para atribuir valores às colunas.fractionTIMETIME

Valores opcionais* fsp*Um número no intervalo de 0 a 6 pode ser fornecido para especificar a precisão dos segundos fracionários. Um valor 0 significa que não há parte decimal. Se omitido, a precisão padrão é 0.

2.1.5YEAR[(4)]

Ano em formato de 4 dígitos. O MySQL YYYYexibe YEARvalores em formato, mas permite que valores sejam atribuídos a YEARcolunas usando strings ou números. YEAROs valores são exibidos como: 1901, 2155ou 0000.

Perceber:

Este tipo de dados foi descontinuado e o suporte foi removido no MySQL 5.7.5 YEAR(2). Para converter uma coluna de 2 bits YEAR(2)em uma coluna de 4 bits YEAR, consulte a Seção 2.5, “Limitações de ANO(2) de 2 bits e migração para ANO de 4 bits” .

Consulte a Seção 2.4, “Tipo de ANO” para obter mais informações sobre YEARo formato de exibição e interpretação dos valores de entrada .

2.1.6 Notas adicionais sobre valores de tempo

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

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

注意:

MySQL 服务器在启用 MAXDB SQL 模式的情况下,TIMESTAMPDATETIME 相同。如果在创建表时启用此模式,则将 TIMESTAMP列创建为DATETIME列。因此,此类列使用 DATETIME显示格式,具有相同的值范围,并且不会自动初始化或更新到当前日期和时间。请参阅 “服务器 SQL 模式”

自 MySQL 5.7.22 起,MAXDB已弃用;将在 MySQL 的未来版本中删除。

2.2 DATE、DATETIME 和 TIMESTAMP 类型

DATEDATETIMETIMESTAMP 类型是相关的。 本节介绍它们的特征、它们的相似之处以及它们的不同之处。MySQL 可以识别 DATEDATETIMETIMESTAMP 的多种格式的值,更多信息参考 “日期和时间文字” 。对于 DATEDATETIME 范围描述,“ supported ”表示虽然早期的值可能有效,但不能保证。

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

DATETIMETipo usado para valores que contêm componentes de data e hora. MySQL 'YYYY-MM-DD hh:mm:ss'recupera e exibe DATETIMEvalores em formato. O intervalo suportado '1000-01-01 00:00:00'é '9999-12-31 23:59:59'.

TIMESTAMPTipo usado para valores que contêm componentes de data e hora. TIMESTAMPTem um intervalo de '1970-01-01 00:00:01'UTC a '2038-01-19 03:14:07'UTC.

Um valor DATETIMEOR TIMESTAMPpode incluir um componente de segundos fracionários finais com precisão de até microssegundos (6 dígitos). Em particular, qualquer parte fracionária do valor inserido DATETIMEna coluna ou será armazenada em vez de descartada. TIMESTAMPDepois de incluir a parte decimal, o formato desses valores é 'YYYY-MM-DD hh:mm:ss[.fraction]', DATETIMEdigite intervalo de valores é '1000-01-01 00:00:00.000000'para '9999-12-31 23:59:59.999999', TIMESTAMPdigite intervalo de valores é '1970-01-01 00:00:01.000000'para '2038-01-19 03:14:07.999999'. A parte fracionária deve sempre ser separada do resto do tempo por um ponto decimal; nenhum outro separador de segundos fracionários é reconhecido. Para obter informações sobre suporte a segundos fracionários no MySQL, consulte Seção 2.7, “Segundos fracionários em valores de tempo” .

TIMESTAMPe DATETIMEos tipos de dados fornecem inicialização e atualização automáticas para a data e hora atuais. Para obter mais informações, consulte a Seção 2.6, “Inicialização e atualização automática de TIMESTAMP e DATETIME” .

O MySQL TIMESTAMPconverte os valores do fuso horário atual para UTC para armazenamento e, em seguida, converte os valores do UTC de volta para o fuso horário atual para recuperação. (Isso não acontece com outros tipos, por exemplo DATETIME) Por padrão, o fuso horário atual para cada conexão é o horário do servidor. O fuso horário pode ser definido por conexão. Contanto que a configuração do fuso horário permaneça inalterada, você poderá retornar o mesmo valor armazenado. Se você armazenar um TIMESTAMPvalor, alterar o fuso horário e recuperar o valor, o valor recuperado será diferente do valor armazenado. Isso acontece porque o mesmo fuso horário não é usado para conversão em ambas as direções. O fuso horário atual está disponível como time_zoneuma variável de sistema. Para obter mais informações, consulte Suporte ao fuso horário do servidor MySQL . Se o
esquema SQL permitir essa conversão, um valor DATEou inválido será convertido em um valor zero ( ou ) do tipo correspondente. O comportamento exato depende se o modo SQL estrito está habilitado e qual modo SQL está habilitado; consulte Modo SQL do Servidor .DATETIMETIMESTAMP'0000-00-00''0000-00-00 00:00:00'NO_ZERO_DATE

Observe certas propriedades de interpretação de valor de data no MySQL:

  • O MySQL permite que os valores sejam especificados como um formato "relaxado" de strings, onde qualquer pontuação pode ser usada como separador entre partes de data ou horas. Essa sintaxe pode ser enganosa em alguns casos. Por exemplo, um valor '10:11:12'pode parecer um valor de tempo porque é usado :, mas se for usado em um contexto de data, '2010-11-12'será interpretado como um ano. O valor '10:45:15'será convertido '0000-00-00'porque '45'não é um mês válido.

    O único separador reconhecido entre as partes de data e hora e a parte de segundos fracionários é o ponto decimal.

  • O servidor exige que os valores de mês e dia sejam válidos, e não apenas nos intervalos de 1 a 12 e 1 a 31 respectivamente. '2004-04-31'Com o modo estrito desativado, isso será convertido em uma data inválida '0000-00-00'e gerará um aviso porque abril não tem 31. Quando o modo estrito estiver ativado, datas inválidas gerarão um erro. Para permitir tais datas, habilite ALLOW_INVALID_DATESPara obter mais informações, consulte Modo SQL do servidor .

  • O MySQL não aceita TIMESTAMPvalores que contenham zeros nas colunas de dia ou mês ou que não sejam datas válidas. A única exceção a esta regra é o valor especial “zero” se o modo SQL permitir este valor. '0000-00-00 00:00:00'O comportamento exato depende se o modo SQL estrito está habilitado e NO_ZERO_DATEqual modo SQL está habilitado; consulte Modo SQL do Servidor .

  • As datas que contêm valores de ano de 2 dígitos são ambíguas porque o século é desconhecido. O MySQL usa as seguintes regras para interpretar valores de ano de 2 dígitos:

    • Os valores do ano no intervalo 00-69tornam-se 2000-2069.
    • Os valores do ano no intervalo 70-99tornam-se 1970-1999.

Consulte também a Seção 2.9, “Anos com dois dígitos em datas” .

2.3 Tipo de TEMPO

O MySQL recupera e exibe valores em 'hh:mm:ss'formato (ou 'hhh:mm:ss'formato para valores grandes de "hora") . Os valores podem variar de a . A parte horária pode ser grande, pois o tipo pode ser usado para representar não apenas uma hora do dia (deve ser inferior a 24 horas), mas também um tempo decorrido ou um intervalo de tempo entre dois eventos (que pode ser muito maior que 24 horas). , mesmo números negativos).TIMETIME'-838:59:59''838:59:59'TIME

O MySQL reconhece TIMEvários formatos de valores, alguns dos quais podem incluir um componente final de segundos fracionários com precisão de até microssegundos (6 dígitos). Consulte "Literais de data e hora" . Para obter informações sobre suporte a segundos fracionários no MySQL, consulte Seção 2.7, “Segundos fracionários em valores de tempo” . Em particular, TIMEqualquer parte fracionária do valor inserido na coluna é armazenada em vez de descartada. Incluindo a parte decimal, TIMEos valores variam de '-838:59:59.000000'até '838:59:59.000000'.

TIMETenha cuidado ao atribuir valores de tempo abreviados às colunas. O MySQL interpreta os valores de abreviação de hora com dois pontos como a hora do dia. Isto é, '11:12'significa '11:12:00'que não é '00:11:12'. O MySQL interpreta valores abreviados sem dois pontos usando a suposição de que os dois dígitos mais à direita representam segundos (ou seja, como tempo decorrido em vez de hora do dia) . Por exemplo, você pode visualizar '1112'e como (12 minutos após 11 horas), mas o MySQL os interpreta como (11 minutos, 12 segundos). Da mesma forma, e são interpretados como . (Resumo pessoal: os valores de tempo com dois pontos são analisados ​​da esquerda para a direita na ordem de "horas, minutos e segundos", e os valores de tempo puramente numéricos sem dois pontos são analisados ​​da direita para a esquerda na ordem de "segundos, minutos e horas")1112'11:12:00''00:11:12''12'12'00:00:12'

O único separador reconhecido entre a parte do tempo e a parte dos segundos fracionários é o ponto decimal.

Por padrão, TIMEos valores fora do intervalo que são válidos são cortados no ponto final mais próximo do intervalo. Por exemplo, '-850:00:00'e '850:00:00'é convertido em '-838:59:59'e '838:59:59'. O valor inválido TIMEé convertido em '00:00:00'. Observe que, como '00:00:00'ele próprio é um valor válido TIME, não há como saber, a partir do valor armazenado na tabela, '00:00:00'se o valor original foi convertido em inválido ou se o valor original foi '00:00:00'.

Para TIMEum tratamento mais rigoroso de valores inválidos, ative o modo SQL estrito para causar erros. Consulte Modo SQL do Servidor .

Tipo de 2,4 anos

YEARType é um tipo de 1 byte usado para representar valores de ano . Pode ser declarado com YEARuma largura de exibição implícita de 4 caracteres ou equivalentemente com uma YEAR(4)largura de exibição explícita.

Perceber

O tipo de dados de 2 bits YEAR(2)está obsoleto e o suporte para ele foi removido no MySQL 5.7.5. Para converter uma coluna de 2 bits em uma coluna YEAR(2)de 4 bits , consulte a Seção 2.5, “Limitações de ANO(2) de 2 bits e migração para ANO de 4 bits” .YEAR

O MySQL YYYYexibe YEARvalores no formato, variando de 1901a 2155e 0000.

YEARAceita valores de entrada em vários formatos:

  • '1901'Uma string de 4 dígitos'2155' no intervalo até .

  • 1901para um número de 4 dígitos2155 no intervalo .

  • '0'Uma string de'99' 1 ou 2 dígitos no intervalo até . O MySQL converte valores no intervalo to em valores em to e valores no intervalo to em valores em to .'0''69'20002069YEAR'70''99'19701999YEAR

  • 0para um número de99 1 ou 2 dígitos no intervalo . O MySQL converte valores no intervalo to em valores em to e valores no intervalo to em valores em to .16920012069YEAR709919701999YEAR

    A inserção do número 0tem um valor exibido 0000e um valor interno de 0000. Se você deseja inserir zeros e interpretá-los 2000, especifique-os como uma string '0' ou '00'.

  • Como YEARresultado de uma função que retorna valores aceitáveis ​​no contexto, NOW()por ex.

Se o modo SQL estrito não estiver habilitado, o MySQL converterá YEARvalores inválidos em 0000.No modo SQL estrito, tentar inserir um YEARvalor inválido gerará um erro.

Consulte também a Seção 2.9, “Anos com dois dígitos em datas” .

2.5 Limitações de ANO(2) de 2 dígitos e migração para ANO de 4 dígitos

Esta seção descreve problemas que podem surgir ao usar YEAR(2)tipos de dados de 2 bits e fornece YEAR(2)informações sobre como converter uma coluna existente em uma coluna de valor anual de 4 dígitos, seja declarando-a como tendo uma YEARlargura de exibição implícita de 4 caracteres, ou equivalentemente YEAR(4)Para exibição explícita largura.

Embora os intervalos de valores internos dos tipos YEAR/ YEAR(4)e obsoletos sejam os mesmos ( to e ), a largura de exibição torna o tipo inerentemente ambíguo porque o valor exibido indica apenas os dois últimos dígitos do valor interno e omite o dígito do século. Em alguns casos, o resultado pode ser uma perda de informação. Por esse motivo, evite usar / em sua aplicação e use-o sempre que o tipo de dados valor do ano for esperado . A partir do MySQL 5.7.5, o suporte para é removido e as colunas existentes de 2 bits devem ser convertidas em colunas de 4 bits antes de serem utilizáveis.YEAR(2)190121550000YEAR(2)YEAR(2)YEARYEAR(4)YEAR(2)YEAR(2)YEAR

2.5.1 YEAR(2)Limitações

YEAR(2)Os problemas com tipos de dados incluem ambigüidade nos valores exibidos e possível perda de informações ao despejar e recarregar valores ou converter em strings.

  • O valor exibido YEAR(2)pode ser ambíguo. Até três YEAR(2)valores com valores internos diferentes podem ter o mesmo valor exibido, como no exemplo a seguir:

    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)
    
  • Se você usar mysqldump para fazer dump da tabela criada no exemplo anterior, o arquivo de dump y2usará os mesmos 2 bits ( 12) para todos os valores. Se a tabela for recarregada a partir do arquivo de despejo, todas as linhas geradas terão um valor interno 2012e um valor exibido de 12, perdendo assim a distinção entre elas.

  • Converte um valor de dados de 2 ou 4 dígitos YEARem formato de string usando seu tipo de dados para exibir a largura. Suponha que uma YEAR(2)coluna e uma coluna YEAR/ YEAR(4)contenham 1970valores. Então, cada um deles obterá os resultados da string de '70'e '1970'. Ou seja, a conversão de um valor interno para uma string perde informações.

  • Ao inserir em uma coluna CSVde uma tabela YEAR(2), valores fora do intervalo 1970to 2069são armazenados incorretamente. Por exemplo, a inserção 2211resultaria em um valor exibido de 11, mas em um valor interno de 2011.

YEARPara evitar esses problemas, use tipos de dados ou de 4 bits em vez de tipos de dados YEAR(4)de 2 bits . YEAR(2)As recomendações para estratégias de migração aparecem mais adiante nesta seção.

(TODO: não concluído)

2.6 Inicialização e atualização automática de TIMESTAMP e DATETIME

TIMESTAMPe DATETIMEas colunas podem ser inicializadas e atualizadas automaticamente para a data e hora atuais (ou seja, o carimbo de data/hora atual).

TIMESTAMPPara qualquer coluna ou na tabela DATETIME, você pode especificar o carimbo de data/hora atual como valor padrão de atualização automática:

  • Colunas inicializadas automaticamente são definidas para o carimbo de data/hora atual das linhas inseridas que não possuem um valor atribuído à coluna.
  • Uma coluna atualizada automaticamente é atualizada automaticamente para o carimbo de data/hora atual quando o valor de qualquer outra coluna na linha muda de seu valor atual. Se todas as outras colunas estiverem definidas com seus valores atuais, as colunas atualizadas automaticamente permanecerão inalteradas. Para evitar que uma coluna atualizada automaticamente seja atualizada quando outras colunas forem alteradas, defina-a explicitamente com seu valor atual. Para atualizar uma coluna atualizada automaticamente se outras colunas não tiverem sido alteradas, defina-a explicitamente com o valor que deveria ter (por exemplo, defina-a como CURRENT_TIMESTAMP).

Além disso, se as variáveis ​​do sistema estiverem desabilitadas, você poderá inicializar ou atualizar qualquer coluna (mas não ) para a data e hora atuais explicit_defaults_for_timestampatribuindo-lhe um valor , a menos que tenha sido definido para permitir um valor.TIMESTAMPDATETIMENULLNULL

Para especificar propriedades automáticas, use DEFAULT CURRENT_TIMESTAMPas ON UPDATE CURRENT_TIMESTAMPcláusulas na definição da coluna. A ordem das cláusulas não importa. Se ambos estiverem presentes na definição da coluna, qualquer um deles poderá aparecer primeiro. CURRENT_TIMESTAMPQuaisquer sinônimos para CURRENT_TIMESTAMPtêm o mesmo significado que . Eles são CURRENT_TIMESTAMP(), NOW(), LOCALTIME, LOCALTIME(), LOCALTIMESTAMPe LOCALTIMESTAMP().

(TODO: Não concluído, o resto é a descrição detalhada dos valores NULL e valores padrão)

2.7 Segundos fracionários em valores de tempo

2.8 Conversão entre tipos de data e hora

2.9 Data do ano com 2 dígitos

3. Tipo de dados string

3.1 Sintaxe do tipo de dados String

3.2 Tipos CHAR e VARCHAR

3.3 Tipos BINÁRIOS e VARBINÁRIOS

3.4 Tipos BLOB e TEXTO

3.5 Tipo ENUM

3.6 Tipo de CONJUNTO

3.1 Sintaxe do tipo de dados String

3.2 Tipos CHAR e VARCHAR

3.3 Tipos BINÁRIOS e VARBINÁRIOS

3.4 Tipos BLOB e TEXTO

3.5 Tipo ENUM

3.6 Tipo de CONJUNTO

4. Tipos de dados espaciais

4.1 Tipos de dados espaciais

4.2 Modelo geométrico OpenGIS

4.3 Formatos de dados espaciais suportados

4.4 Boa formação geométrica e validade

4.5 Criar colunas espaciais

4.6 Preenchendo colunas espaciais

4.7 Obtenção de dados espaciais

4.8 Análise espacial de otimização

4.9 Criar índice espacial

4.10 Usando índices espaciais

4.1 Tipos de dados espaciais

4.2 Modelo geométrico OpenGIS

4.3 Formatos de dados espaciais suportados

4.4 Boa formação geométrica e validade

4.5 Criar colunas espaciais

4.6 Preenchendo colunas espaciais

4.7 Obtenção de dados espaciais

4.8 Análise espacial de otimização

4.9 Criar índice espacial

4.10 Usando índices espaciais

5. Tipo de dados JSON

5.1. Criando valores JSON
5.2. Normalização, mesclagem e empacotamento automático de valores JSON
5.3. Pesquisando e modificando valores JSON
5.4. Sintaxe do caminho JSON
5.5. Comparação e classificação de valores JSON
5.6. Convertendo entre JSON e valores não JSON
5.7. JSON Agregação de valores
5.8, referências relacionadas

A partir do MySQL 5.7.8, o MySQL oferece suporte a tipos de dados nativos definidos pela RFC 7159JSON , que podem efetivamente acessar dados em documentos JSON (JavaScript Object Notation). Esse tipo de dados tem as seguintes vantagens em relação ao armazenamento de strings formatadas em JSON em uma coluna de string:

  • Valide automaticamente JSONdocumentos JSON armazenados em colunas. Documentos inválidos geram erros.
  • Formato de armazenamento otimizado. Os documentos JSON armazenados JSONem colunas são convertidos em um formato interno que permite a leitura rápida dos elementos do documento. Quando o servidor precisar ler posteriormente um valor JSON armazenado nesse formato binário, ele não precisará analisar o valor da representação textual. A estrutura do formato binário permite que o servidor procure subobjetos ou valores aninhados diretamente por chave ou índice de array sem precisar ler todos os valores antes ou depois deles no documento.

JSONO espaço necessário para armazenar um documento é aproximadamente o mesmo que LONGBLOBou LONGTEXT; consulte a Seção 7, “Requisitos de armazenamento de tipos de dados” para obter detalhes . JSONÉ importante lembrar que o tamanho de qualquer documento JSON armazenado em uma coluna é limitado pelo max_allowed_packetvalor da variável do sistema. (Pode ser maior que esse valor quando o servidor manipula valores JSON internamente na memória; o limite se aplica quando o servidor os armazena.)

As colunas JSONnão podem ter NULLvalores não padrão.

Além dos JSONtipos de dados, há um conjunto de funções SQL que permitem operações em valores JSON, como criação, manipulação e pesquisa. A discussão a seguir mostra exemplos dessas operações. Consulte a Seção 12.18, “Funções JSON” para obter detalhes sobre funções individuais .

Também é fornecido um conjunto de funções espaciais para operar em valores GeoJSON. Consulte Funções GeoJSON espaciais .

JSONAs colunas, como outras colunas de tipo binário, não são indexadas diretamente; em vez disso, você cria um índice na coluna gerada para JSONextrair um valor escalar da coluna. Para obter um exemplo detalhado, consulte Indexação de colunas geradas para fornecer índices de colunas JSON.

O otimizador MySQL também procura índices compatíveis em colunas virtuais que correspondam a expressões JSON.

MySQL NDB Cluster 7.5 (7.5.2 e posterior) oferece suporte a colunas e funções JSON do MySQL, incluindo a criação de índices em colunas JSONgeradas a partir de colunas como uma solução alternativa para colunas que não podem ser indexadas. Cada tabela suporta até 3 colunas.JSONJSONNDBJSON

As próximas seções fornecem informações básicas sobre a criação e manipulação de valores JSON.

5.1. Criar valor JSON

Uma matriz JSON contém uma lista de valores separados por vírgulas e entre caracteres [e :]

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

Um objeto JSON contém um conjunto de pares de valores-chave separados por vírgulas e entre caracteres { de e comercial }:

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

Conforme mostrado no exemplo, matrizes e objetos JSON podem conter valores escalares, ou seja, strings ou números, literais nulos JSON ou literais JSON Booleanos verdadeiros ou falsos. As chaves em objetos JSON devem ser strings. Valores escalares de hora (data, hora ou datahora) também são permitidos:

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

O aninhamento é permitido em elementos de matriz JSON e chaves de objeto JSON:

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

Você também pode obter valores JSON das muitas funções que o MySQL fornece para esse propósito (veja Seção 12.18.2, “Funções para criar valores JSON” ), bem como converter valores de outros tipos usando-os CAST(value AS JSON)(veja Convertendo entre JSON) e valor não JSON ) para JSONdigitar. Os próximos parágrafos descrevem como o MySQL lida com os valores JSON fornecidos como entrada.

No MySQL, os valores JSON são escritos como strings. O MySQL analisa qualquer string usada em um contexto que espera um valor JSON e gera um erro se não for válido como JSON. Esses contextos incluem a inserção de valores em JSONcolunas com tipos de dados e a passagem de argumentos para funções que esperam valores JSON (geralmente mostrados como * json_docou * json_valna documentação das funções JSON do MySQL), conforme mostrado no exemplo a seguir:

  • JSONUma tentativa de inserir o valor na coluna será bem-sucedida se o valor for um valor JSON válido , mas falhará se não for:
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,'.

在此类错误消息中,“ at position N ”的位置是从 0 开始的,但只能将其视为在值中实际发生问题的位置的粗略指示。

  • JSON_TYPE()函数需要一个 JSON 参数并尝试将其解析为 JSON 值。如果有效,将返回 JSON 类型的值,否则产生错误:

    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 使用 utf8mb4 字符集(character set) 和 utf8mb4_bin 字符序(collation,字符排序规则,bin表示用编码值进行比较) 规则处理 JSON 上下文中使用的字符串。其他字符集中的字符串根据需要转换utf8mb4为。(对于asciior utf8字符集中的字符串,不需要转换,因为asciiandutf8utf8mb4 的子集。)

说明(自己补充)

collation,字符排序规则。_bin 表示用编码值(二进制)进行比较,_ci 表示大小写不敏感(Insensitive),_cs 表示大小写敏感

也可以指定字符串的值是否区分大小写,与mysql的表名称是否区分大小写不同。

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)

作为使用文字字符串编写 JSON 值的替代方法,存在用于从组件元素组合 JSON 值的函数。JSON_ARRAY()接受一个(可能是空的)值列表并返回一个包含这些值的 JSON 数组:

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

JSON_OBJECT()获取一个(可能为空的)键值对列表并返回一个包含这些对的 JSON 对象:

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

JSON_MERGE()接受两个或多个 JSON 文档并返回组合结果:

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

有关合并规则的信息,请参阅 JSON 值的规范化、合并和自动包装

JSON 值可以分配给用户定义的变量:

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)

No entanto, uma variável definida pelo usuário não pode ser JSONum tipo de dados, portanto, embora @jpareça um valor JSON no exemplo anterior e tenha o mesmo conjunto de caracteres e agrupamento de um valor JSON, ela não possui um JSONtipo de dados. Em vez disso, JSON_OBJECT()o resultado é convertido em uma string quando atribuído a uma variável (na verdade, eu medi para ser convertido em longtexttipo).

A string gerada pela conversão de um valor JSON possui um conjunto de caracteres utf8mb4e um agrupamento utf8mb4_bin:

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

Por utf8mb4_binser um agrupamento binário, as comparações de valores JSON diferenciam maiúsculas de 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)

A distinção entre maiúsculas e minúsculas também se aplica a JSON's nulle truecaracteres false, que devem ser sempre escritos em letras minúsculas:

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

A distinção entre maiúsculas e minúsculas dos caracteres JSON difere da distinção entre maiúsculas e minúsculas do SQL NULLe TRUEdos FALSEcaracteres, que podem estar em qualquer letra:

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

Às vezes pode ser necessário ou desejável inserir caracteres de aspas ( "aspas duplas ou simples ') em um documento JSON. Para este exemplo, suponha que você deseja inserir alguns objetos JSON em uma tabela criada usando as instruções SQL mostradas aqui, que contêm strings representando as instruções que representam alguns fatos práticos sobre o MySQL, cada um relevante para o par de strings de palavras-chave apropriado:

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 mascotfrase específica usada como chave, você pode usar o operador caminho da coluna ->da seguinte maneira:

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

Isso deixa a barra invertida intacta, bem como as aspas ao redor. Para exibir o valor desejado usando como key mascot, mas sem aspas ou caracteres de escape, use o operador de caminho embutido ->>da seguinte maneira:

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

Se o modo SQL do servidor estiver habilitado NO_BACKSLASH_ESCAPES, o exemplo anterior não funcionará corretamente. Se esse modo estiver definido, os literais de objeto JSON poderão ser inseridos usando uma única barra invertida em vez de uma barra invertida dupla, e as barras invertidas serão preservadas. Se JSON_OBJECT()você utilizar esta função ao realizar uma inserção e este modo estiver configurado, você deverá alternar aspas simples e duplas, conforme a seguir:

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

Para obter mais informações sobre o efeito desse modo em caracteres de escape em valores JSON, consulte JSON_UNQUOTE()a descrição da função.

5.2. Padronização, fusão e empacotamento automático de valores JSON

5.2.1. Valores JSON normalizados

Quando uma string é analisada e considerada um documento JSON válido, ela também é normalizada: membros com chaves duplicadas de chaves encontradas anteriormente no documento são descartados (mesmo que os valores sejam diferentes). O valor do objeto gerado pela chamada a seguir JSON_OBJECT()não inclui o segundo key1elemento porque a chave aparece antes do valor:

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

Perceber

Este tratamento de "primeira chave ganha" para chaves duplicadas é inconsistente com RFC 7159 . Este é um problema conhecido no MySQL 5.7 e foi corrigido no MySQL 8.0. (Erro nº 86866, Erro nº 26369555)

O MySQL também descarta espaços extras entre chaves, valores ou elementos no documento JSON original e deixa (ou insere, se necessário) um espaço após cada vírgula ( ,) ou dois pontos ( ) quando exibido . :Isso é feito para melhorar a legibilidade.

Funções MySQL que produzem valores JSON (veja Seção 12.18.2, “Funções que criam valores JSON” ) sempre retornam valores normalizados.

Para melhorar a eficiência da pesquisa, ele também classifica as chaves dos objetos JSON. Você deve estar ciente de que os resultados dessa classificação estão sujeitos a alterações e não há garantia de consistência entre as versões .

5.2.2. Mesclar valores JSON

No contexto de combinação de vários arrays, vários arrays são combinados em um único array concatenando o array nomeado posteriormente ao final do primeiro array . No exemplo a seguir, JSON_MERGE()seus parâmetros são combinados em um array:

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

A mesclagem também é realizada ao inserir valores em colunas JSON, conforme mostrado abaixo:

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

Quando vários objetos são combinados, um objeto é produzido. Se vários objetos tiverem a mesma chave, o valor dessa chave no objeto mesclado resultante será uma matriz contendo o valor da chave:

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. Quebra automática de valores JSON

  • Quebra automática de valores não array

Valores não-array usados ​​​​em contextos que exigem valores de array são automaticamente agrupados : o valor é cercado por caracteres [e ]para convertê-lo em um array. Nas instruções a seguir, cada argumento é automaticamente agrupado como uma matriz ( [1], [2]). Em seguida, combine-os para produzir um único array resultante:

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

Mesclar valores de array e objeto agrupando automaticamente o objeto em um array e mesclando os dois arrays:

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. Pesquise e modifique valores JSON

As expressões de caminho JSON selecionam um valor em um documento JSON.

As expressões de caminho são úteis para funções que extraem parte de um documento JSON ou modificam um documento JSON para especificar onde operar no documento. namePor exemplo, a consulta a seguir extrai o valor de um membro com uma chave de um documento JSON :

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

A sintaxe do caminho usa um $caractere inicial para identificar o documento JSON em consideração, seguido por expressões opcionais após o seletor que, por sua vez, especifica partes mais específicas do documento:

  • Um ponto seguido pelo nome da chave nomeia o membro no objeto usando a chave fornecida. Se o nome sem aspas não for válido em uma expressão de caminho (por exemplo, contém espaços), o nome da chave deverá ser especificado entre aspas duplas.

  • [N]Seguir imediatamente pathsignifica selecionar um elemento pathcom o subscrito do nome do array ( ) , que é um número inteiro começando em zero. Se a seleção não for uma matriz, * *[0] é equivalente a :NNpathpathpath

    mysql> SELECT JSON_SET('"x"', '$[0]', 'a');
    +------------------------------+
    | JSON_SET('"x"', '$[0]', 'a') |
    +------------------------------+
    | "a"                          |
    +------------------------------+
    1 row in set (0.00 sec)
    
  • O caminho pode conter caracteres *curinga **:

    • .[*]Calcule os valores de todos os membros em um objeto JSON.
    • [*]Calcule o valor de todos os elementos em uma matriz JSON.
    • prefix**suffixConta todos os caminhos prefixcomeçando e terminando com .suffix
  • Caminhos que não existem no documento (avaliados como dados inexistentes) são avaliados como NULL.

Vamos $fazer referência a este array JSON de três elementos:

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

Então:

  • $[0]Avaliado como 3.
  • $[1]Avaliado como {"a": [5, 6], "b": 10}.
  • $[2]Avaliado como [99, 100].
  • $[3]Avalia como NULL(refere-se ao quarto elemento do array, que não existe).

Como $[1]são $[2]avaliados como valores não escalares, eles podem ser usados ​​como base para expressões de caminho mais específicas que selecionam valores aninhados. exemplo:

  • $[1].aAvaliado como [5, 6].
  • $[1].a[1]Avaliado como 6.
  • $[1].bAvaliado como 10.
  • $[2][0]Avaliado como 99.

Conforme mencionado anteriormente, se o nome da chave não for válido em uma expressão de caminho, os componentes do caminho da chave deverão ser colocados entre aspas. Vamos $nos referir a este valor:

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

Ambas as chaves contêm um espaço e devem ser colocadas entre aspas:

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

Um caminho usando curingas é avaliado como uma matriz que pode conter vários 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]                                                  |
+------------------------------------------------------------+

No exemplo a seguir, path $**.bavalia vários caminhos ( $.a.bsum $.c.b) e produz uma matriz de valores de caminho correspondentes:

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

No MySQL 5.7.9 e posterior, você pode usar column->pathidentificadores de coluna JSON e expressões de caminho JSON como JSON_EXTRACT(column, path)sinônimos para Para obter mais informações, consulte a Seção 12.18.3, “Funções para pesquisar valores JSON” . Consulte também Indexar colunas geradas para fornecer índices de colunas JSON .

Algumas funções pegam um documento JSON existente, modificam-no de alguma forma e retornam o documento modificado como resultado. As expressões de caminho indicam onde as alterações são feitas no documento. Por exemplo, JSON_SET()cada função JSON_INSERT()e JSON_REPLACE()aceita um documento JSON, além de um ou mais pares de caminho/valor que descrevem onde modificar o documento e os valores a serem usados. Essas funções diferem na forma como lidam com valores existentes e inexistentes no documento.

Considere este documento:

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

JSON_SET()Substitua o valor de um caminho existente e adicione o valor de um caminho que não 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]]      |
+--------------------------------------------+

Nesse caso, o caminho $[1].b[0]seleciona um valor existente ( true), que é substituído pelo seguinte valor do parâmetro de caminho ( 1). O caminho $[2][2]não existe, então o valor correspondente ( 2) é adicionado aos $[2]valores selecionados.

JSON_INSERT()Adicione novos valores sem substituir os 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()Substitua os valores existentes e ignore os novos 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]]             |
+------------------------------------------------+

Os pares caminho/valor são avaliados da esquerda para a direita. O documento gerado pela avaliação de um par torna-se o novo valor para avaliação do próximo par.

JSON_REMOVE()Aceita um documento JSON e um (ou mais) caminhos que especificam os valores a serem removidos do documento. O valor de retorno é o documento original menos quaisquer seleções de caminho existentes no 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]}]                              |
+---------------------------------------------------+

Os caminhos têm os seguintes efeitos:

  • $[2]Combine [10, 20]e exclua-o.
  • O primeiro $[1].b[1]corresponde bao elemento falsee o remove.
  • O segundo $[1].b[1]não corresponde a nenhum elemento: o elemento que se espera corresponder foi removido, o caminho não existe mais e não tem efeito.

5.4. Sintaxe do caminho JSON

Muitas das funções JSON suportadas pelo MySQL e descritas em outras partes deste manual (consulte a Seção 12.18, “Funções JSON” ) requerem expressões de caminho para identificar elementos específicos em um documento JSON. Um caminho consiste em uma série de caminhos e uma ou mais ramificações de caminho . Para caminhos usados ​​em funções JSON do MySQL, o escopo é sempre o documento que está sendo pesquisado ou manipulado, $representado pelo caractere inicial. As ramificações do caminho (pernas do caminho) são separadas por caracteres de ponto final ( .). Uma célula na matriz é [N]representada por , onde Né um número inteiro não negativo. O nome da chave deve ser uma string entre aspas duplas ou um identificador ECMAScript válido (consulte http://www.ecma-international.org/ecma-262/5.1/#sec-7.6). Expressões de caminho (como texto JSON) devem ser codificadas usando o conjunto de caracteres ascii, utf8ou . utf8mb4Outras codificações de caracteres são implicitamente forçadas a utf8mb4.A sintaxe completa é a seguinte:

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 mencionado anteriormente, no MySQL, o escopo de um caminho é sempre o documento que está sendo operado, expresso como $. Você pode '$'usá-lo como sinônimo de um documento em uma expressão de caminho JSON.

notas

Algumas implementações suportam referências de coluna de intervalo de caminho JSON; atualmente, o MySQL não suporta estas referências.

Curingas *e **tags são usados ​​da seguinte forma:

  • .*Representa os valores de todos os membros do objeto.

  • [*]Representa os valores de todas as células da matriz.

  • [prefix]**suffixRepresenta todos os caminhos prefixcomeçando e terminando com . é opcional, mas obrigatório; em outras palavras, o caminho não pode terminar em .suffixprefixsuffix**

    Além disso, o caminho pode não conter a sequência ***(3 asteriscos).

Para obter exemplos de sintaxe de caminho, consulte as descrições de várias funções JSON que usam caminhos como argumentos, como JSON_CONTAINS_PATH(), JSON_SET()e JSON_REPLACE(). Consulte a descrição da função para obter um exemplo de uso * dos caracteres curinga e .**JSON_SEARCH()

5.5. Comparação e classificação de valores JSON

Você pode comparar valores JSON usando =os operadores , <, <=, >, >=, <>e .!=<=>

Os seguintes operadores e funções de comparação ainda não são compatíveis com valores JSON:

A solução alternativa para os operadores e funções de comparação listados acima é converter os valores JSON em tipos de dados numéricos ou de string nativos do MySQL para que tenham tipos escalares não JSON consistentes.

A comparação dos valores JSON ocorre em dois níveis. A comparação de primeiro nível é baseada no tipo JSON do valor comparado. Se os tipos forem diferentes, o resultado da comparação dependerá apenas de qual tipo tem maior precedência. Se dois valores tiverem o mesmo tipo JSON, uma comparação de segundo nível será realizada usando regras específicas do tipo.

A lista a seguir mostra a prioridade dos tipos JSON, da prioridade mais alta à prioridade mais baixa. (O nome do tipo é JSON_TYPE()o nome retornado pela função.) Os tipos que aparecem juntos em uma linha têm a mesma precedência. Qualquer valor do tipo JSON listado anteriormente na lista é maior que qualquer valor do tipo JSON listado posteriormente na lista.

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

Para valores JSON da mesma precedência, as regras de comparação são específicas do tipo:

  • BLOB

    NCompara os primeiros bytes de dois valores , onde Né o número de bytes no valor mais curto. Se os primeiros Nbytes de dois valores forem iguais, o valor mais curto será classificado antes do valor mais longo.

  • BIT

    BLOBMesmas regras do .

  • OPAQUE

    BLOBMesmas regras do . OPAQUEType é um tipo não classificado.

  • DATETIME

    Os valores de pontos de tempo anteriores são classificados antes dos valores que representam pontos de tempo posteriores. Dois valores são iguais se vieram originalmente do MySQL DATETIMEe TIMESTAMPdo tipo respectivamente, se representarem o mesmo momento.

  • TIME

    O menor dos dois valores de tempo é classificado antes do maior.

  • DATE

    As datas mais antigas são classificadas antes das datas posteriores.

  • ARRAY

    Duas matrizes JSON são iguais se tiverem o mesmo comprimento e os valores nas posições correspondentes na matriz forem iguais.

    Se as matrizes não forem iguais, sua ordem será determinada pelo primeiro elemento na posição onde existe a diferença. Arrays com valores menores nessa posição são classificados primeiro. Se todos os valores do array mais curto forem iguais aos valores correspondentes no array mais longo, o array mais curto será classificado primeiro.

    exemplo:

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

    Os caracteres falsos do JSON são menores que os caracteres verdadeiros do JSON.

  • OBJETO

    Dois objetos JSON são iguais se tiverem o mesmo conjunto de chaves e cada chave tiver o mesmo valor em ambos os objetos.

    exemplo:

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

    A ordem de dois objetos desiguais não é especificada, mas é determinística. (Nota: não entendi esta frase)

  • STRING

    As strings são classificadas lexicamente nos utf8mb4primeiros bytes codificados nas duas strings que estão sendo comparadas , onde é o comprimento da string mais curta. Se os primeiros bytes de duas strings forem iguais, a string mais curta será considerada menor que a string mais longa.NNN

    exemplo:

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

    Essa classificação é equivalente a usar utf8mb4_binagrupamento para classificar strings SQL. Por causa utf8mb4_bindo agrupamento binário, as comparações de valores JSON diferenciam maiúsculas de minúsculas:

    "A" < "a"
    
  • INTEGER,DOUBLE

    Os valores JSON podem conter números exatos e aproximados. Consulte a Seção 9.1.2, “Literais de Números” para uma discussão geral sobre esses tipos de números .

    As regras para comparar tipos numéricos nativos do MySQL são discutidas na Seção 12.3, “Conversões de tipo na avaliação de expressões” , mas as regras para comparar tipos numéricos em valores JSON são um pouco diferentes:

    • Nas comparações entre duas colunas usando MySQL nativo INTe DOUBLEtipos numéricos respectivamente, sabe-se que todas as comparações envolvem números inteiros e duplos, portanto, para todas as linhas, os inteiros são convertidos em duplos. Ou seja, converta um número exato em um número aproximado.

    • Por outro lado, se uma consulta comparar duas colunas JSON contendo números, ela não poderá saber antecipadamente se os números são inteiros ou duplos. Para fornecer o comportamento mais consistente em todas as linhas, o MySQL converte números aproximados em números exatos. A ordenação resultante é consistente e não perde a precisão dos números de valores exatos. Por exemplo, dados os escalares 9223372036854775805, 9223372036854775806, 9223372036854775807 e 9,223372036854776e18, a ordem é a seguinte:

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

    Se a comparação JSON usar regras de comparação numérica não JSON, poderá ocorrer uma ordenação inconsistente. As regras comuns de comparação de números do MySQL produzem a seguinte ordem:

    • Comparação inteira:

      9223372036854775805 < 9223372036854775806 < 9223372036854775807
      

      (indefinido 9.223372036854776e18)

    • Comparação dupla:

      9223372036854775805 = 9223372036854775806 = 9223372036854775807 = 9.223372036854776e18
      

Para qualquer NULLcomparação de valores JSON com SQL, o resultado é UNKNOWN.

Para comparações de valores JSON e não JSON, os valores não JSON são convertidos em JSON de acordo com as regras da tabela a seguir e, em seguida, os valores são comparados conforme descrito anteriormente.

5.6. Converter entre valores JSON e não JSON

A tabela a seguir resume as regras que o MySQL segue ao converter entre valores JSON e outros tipos de valores:

Tabela 11.3 Regras de conversão JSON

Outros tipos CAST (outros tipos AS JSON) CAST(JSON AS outros tipos)
JSON Inalterado Inalterado
tipo de caractere utf8 ( utf8mb4, utf8, ascii) A string é analisada em um valor JSON. Os valores JSON são serializados em utf8mb4strings.
Outros tipos de caracteres Outras codificações de caracteres são convertidas implicitamente em utf8mb4tipos de caracteres e processadas de acordo com o conjunto de caracteres utf8. Os valores JSON são serializados em utf8mb4strings e depois convertidos em outras codificações de caracteres. Os resultados podem não fazer sentido.
NULL Retorna NULLum valor JSON do tipo . não aplicável.
Tipo GEO ST_AsGeoJSON()Converta valores GEO em documentos JSON chamando . Operação ilegal. Solução: Passe CAST(json_val AS CHAR)o resultado de para passar ST_GeomFromGeoJSON()o resultado de to ST_GeomFromGeoJSON().
todos os outros tipos Gera um documento JSON que consiste em um único valor escalar. Sucesso se o documento JSON contiver um único valor escalar do tipo de destino e o valor escalar puder ser convertido no tipo de destino. Caso contrário, retorne NULLe gere um aviso.

Para valores JSON ORDER BYe GROUP BYfunciona de acordo com os seguintes princípios:

  • Os valores escalares JSON são classificados usando as mesmas regras da discussão anterior.
  • Para classificação ascendente, os SQL NULLsão classificados antes de todos os valores JSON, incluindo literais JSON NULL; para classificação descendente, os SQL são NULLclassificados depois de todos os valores JSON, incluindo literais JSON NULL.
  • A chave de classificação de um valor JSON é limitada pelo max_sort_lengthvalor de uma variável do sistema, portanto max_sort_length, é considerada igual se os primeiros bytes forem iguais (e só então diferirem).
  • A classificação de valores não escalares não é suportada no momento e ocorre um aviso.

对于排序,将 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 armazenamento de tabela NDB

7.3. Requisitos de armazenamento de tipo digital

7.4. Requisitos de armazenamento de tipo de data e hora

7.5. Requisitos de armazenamento do tipo string

7.6. Requisitos de armazenamento de tipo de espaço

7.7. Requisitos de armazenamento JSON

7.8. Referências relacionadas

Os requisitos de armazenamento para dados de tabela em disco dependem de vários fatores. Diferentes mecanismos de armazenamento representam tipos de dados e armazenam dados brutos de maneira diferente. Os dados da tabela podem ser compactados para uma coluna ou para uma linha inteira, complicando os cálculos dos requisitos de armazenamento da tabela ou da coluna.

Apesar das diferenças no layout de armazenamento em disco, a API interna do MySQL usada para comunicar e trocar informações sobre as linhas da tabela usa estruturas de dados consistentes que funcionam em todos os mecanismos de armazenamento.

Esta seção inclui orientação e informações sobre os requisitos de armazenamento para cada tipo de dados suportado pelo MySQL, incluindo o formato interno e o tamanho do mecanismo de armazenamento para tipos de dados representados usando tamanhos fixos. As informações são listadas por categoria ou mecanismo de armazenamento.

A representação interna da tabela tem um tamanho máximo de linha de 65.535 bytes, embora o mecanismo de armazenamento possa suportar linhas maiores. Este número não inclui BLOBas colunas OR TEXT, que representam apenas 9 a 12 bytes deste tamanho. Para dados BLOBe TEXT, as informações são armazenadas internamente em uma área de memória diferente do buffer de linha. Diferentes mecanismos de armazenamento lidam com a alocação e o armazenamento desses dados de maneira diferente, com base nos métodos usados ​​para lidar com o tipo correspondente. Para obter mais informações, consulte Capítulo 15, Mecanismos de armazenamento alternativos e Seção 8.4.7, “Limitações no número de colunas da tabela e tamanhos de linhas” .

7.1. Requisitos de armazenamento de tabelas InnoDB

Para obter informações sobre InnoDBos requisitos de armazenamento de tabelas, consulte a Seção 14.11, “Formato de linha do InnoDB” .

7.2. Requisitos de armazenamento de tabela NDB

(pular sobre)

7.3. Requisitos de armazenamento de tipo digital

tipo de dados precisa de armazenamento
TINYINT 1 byte
SMALLINT 2 bytes
MEDIUMINT 3 bytes
INT,INTEGER 4 bytes
BIGINT 8 bytes
FLOAT(p) 4 bytes (0 <= p<= 24), 8 bytes (25 <= p<= 53)
FLOAT 4 bytes
DOUBLE [PRECISION],REAL 8 bytes
DECIMAL(M,D),NUMERIC(M,D) comprimento variável; veja a discussão abaixo
BIT(M) Aproximadamente ( M+7)/8 bytes

DECIMALOs valores das colunas (e NUMERIC) são representados usando um formato binário que agrupa nove dígitos decimais (base 10) em quatro bytes. O armazenamento das partes inteiras e fracionárias de cada valor é determinado separadamente. Cada múltiplo do número de nove dígitos requer quatro bytes, e o número "restante" requer uma porção de quatro bytes. A tabela a seguir fornece o espaço de armazenamento necessário para números extras.

dígitos restantes Número de bytes
0 0
1, 2 1
3, 4 2
5, 6 3
7, 8 4

7.4. Requisitos de armazenamento de tipo de data e hora

Para as colunas TIME, DATETIMEe TIMESTAMP, as tabelas criadas antes do MySQL 5.6.4 requerem espaço de armazenamento diferente das tabelas criadas a partir da versão 5.6.4. Isto se deve às alterações no 5.6.4 que permitem que esses tipos tenham uma parte fracionária, que requer de 0 a 3 bytes.

tipo de dados O armazenamento é necessário antes do MySQL 5.6.4 Espaço de armazenamento necessário para MySQL 5.6.4
YEAR 1 byte 1 byte
DATE 3 bytes 3 bytes
TIME 3 bytes 3 bytes + segundos fracionários armazenados
DATETIME 8 bytes 5 bytes + segundos fracionários armazenados
TIMESTAMP 4 bytes 4 bytes + segundos fracionários armazenados

从 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、使用来自其他数据库引擎的数据类型

Acho que você gosta

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