Tipos de dados Mysql - documentos oficiais - notas de estudo
Índice
- 1 tipo de dados numérico
- 2 Tipos de dados de data e hora
- 3 Tipo de dados de string
- 4 tipos de dados espaciais
- 5 tipo de dados JSON
- 6 Valor padrão do tipo de dados
- 7 Requisitos de armazenamento de tipo de dados
- 8 Escolha o tipo correto para a coluna
- 9 Usando tipos de dados de outros mecanismos de banco de dados
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 JSON
tipos 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.M
O 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 aM
-2. -
*
fsp
* Aplica-se aos tiposTIME
,DATETIME
eTIMESTAMP
e representa a precisão de segundos fracionários; ou seja, o número de segundos fracionários após o ponto decimal. Ofsp
valor * *, 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,
M
representa 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
- Ponto fixo:
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. M
Representa o número de dígitos em cada valor, de 1
até 64
. Se M
omitido, o padrão é 1
.
1.1.2TINYINT[(M)] [UNSIGNED] [ZEROFILL]
Um número inteiro muito pequeno, ocupando 1
bytes. O intervalo assinado é -2[^7] = -128
a 2[^7]-1 = 127
. O intervalo não assinado é 0
2[^8]-1 = 255
.
M
Indica 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 TRUE
e FALSE
são apenas apelidos para 1
e 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 2
diferente de TRUE
e FALSE
porque 2
nem é igual 1
nem igual a 0
.
1.1.4SMALLINT[(M)] [UNSIGNED] [ZEROFILL]
Um pequeno inteiro, ocupando 2
bytes. O intervalo assinado é -2[^15] = -32768
a 2[^15]-1 = 32767
. O intervalo não assinado é 0
2[^16]-1 = 65535
.
1.1.5MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]
Um número inteiro de tamanho médio em 3
bytes. O intervalo assinado é -2[^23] = -8388608
a 2[^23]-1 = 8388607
. O intervalo não assinado é 0
2[^24]-1 = 16777215
.
1.1.6INT[(M)] [UNSIGNED] [ZEROFILL]
Um número inteiro de tamanho normal, em 4
bytes. O intervalo assinado é -2[^31] = -2147483648
a 2[^31]-1 = 2147483647
. O intervalo não assinado é 0
2[^32]-1 = 4294967295
.
1.1.7INTEGER[(M)] [UNSIGNED] [ZEROFILL]
Este tipo é INT
sinônimo de .
1.1.8BIGINT[(M)] [UNSIGNED] [ZEROFILL]
Um número inteiro grande, ocupando 8
bytes. O intervalo assinado é -2[^63] = -9223372036854775808
a 2[^63]-1 = 9223372036854775807
. O intervalo não assinado é 0
2[^64]-1 = 18446744073709551615
.
SERIAL
Sim, BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE
aliás.
BIGINT
Algumas coisas que você deve observar sobre colunas :
-
Toda aritmética é feita usando valores
BIGINT
OR 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 paraDOUBLE
9223372036854775807
BIGINT
DOUBLE
O MySQL pode lidar com
BIGINT
as seguintes situações:- Ao usar números inteiros
BIGINT
para armazenar grandes valores não assinados em colunas. BIGINT
Quando colunas são usadas emMIN(*
col_name*)
eMAX(*
col_name*)
- Ao usar um operador onde ambos os operandos são inteiros (
+
,-
,*
etc.).
- Ao usar números inteiros
-
BIGINT
Sempre é 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 .+
*
BIGINT
9223372036854775807
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 contadosM
. Se **D
for 0, o valor não possui ponto decimal ou parte decimal.
( DECIMAL
O texto literal também tem comprimento limitado; consulte Tratamento de expressões .)
Se especificado UNSIGNED
, valores negativos não serão permitidos.
DECIMAL
Todos 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 DECIMAL
sinônimos de . FIXED
Sinô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+38
to -1.175494351E-38
e 0
to . 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-38
3.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 FLOAT
pode 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. p
Representa a precisão em bits, mas o MySQL usa esse valor apenas para determinar se deve usar FLOAT
ou DOUBLE
usar o tipo de dados gerado. Se * p
for de 0 a 24, o tipo de dados se tornará FLOAT
NenhumM
* ou D
** o valor. Se ** p
for de 25 a 53, o tipo de dados se tornará DOUBLE
Nenhum M
ouD
Valor. O intervalo da coluna de resultados é igual aos tipos de dados simples FLOAT
ou duplos DOUBLE
descritos 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+308
to -2.2250738585072014E-308
e 0
to . 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-308
1.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]
- Esses tipos são
DOUBLE
sinônimos de . Exceção: seREAL_AS_FLOAT
o modo SQL estiver ativado, entãoREAL
é sinônimo deFLOAT
em vez deDOUBLE
.
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 TINYINT
e . A tabela a seguir mostra o espaço de armazenamento e o intervalo necessários para cada tipo inteiro.MEDIUMINT
BIGINT
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
DECIMAL
e NUMERIC
os 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 DECIMAL
também se aplica NUMERIC
.
O MySQL DECIMAL
armazena 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" .
DECIMAL
A 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 salary
o intervalo de valores que podem ser armazenados na coluna varia de -999.99
a 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 M
o valor de. MySQL suporta essas duas formas diferentes de DECIMAL
sintaxe. M
O valor padrão é 10.
Se o decimal for 0, DECIMAL
o valor não contém ponto decimal ou parte decimal.
DECIMAL
O número máximo de dígitos é 65, mas o intervalo real de uma determinada DECIMAL
coluna 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
FLOAT
e DOUBLE
os 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 FLOAT
coluna 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é M
dígitos pode ser armazenado, dos quais D
os 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.00009
na FLOAT(7,4)
coluna, o resultado aproximado é que 999.0001
o 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 FLOAT
ou DOUBLE PRECISION
não especificar precisão ou número de dígitos.
Tipo de valor de 1,5 bits - BIT
BIT
O tipo de dados é usado para armazenar valores de "bits" (binários). Um BIT(M)
tipo permite o armazenamento M
de valores de dígitos binários. M
O intervalo pode ser de 1 a 64.
Para especificar o valor de um "bit", pode-se usar a notação binária b'value'
. b
Indica 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 7
e respectivamente 128
. Consulte "Literal de valor posicional" .
Se um M
valor 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 101
existem apenas 3 dígitos binários, o que é insuficiente para os 6
dígitos esperados, o preenchimento esquerdo é suficiente 0
para compensar 6
os dígitos e o número b'000101'
é armazenado no mysql.
Cluster NDB : O tamanho máximo combinado de NDB
todas 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 t1
tenha 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 DATA
e UPDATE
de 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 BIGINT
valor 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 DECIMAL
intervalo 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 é UNSIGNED
do 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_SUBTRACTION
o 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 UNSIGNED
uma coluna inteira, o resultado será reduzido para o valor máximo do tipo de coluna ou NO_UNSIGNED_SUBTRACTION
para 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.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
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” .DATETIME
TIMESTAMP
YEAR
TIMESTAMP
DATETIME
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-99
Os valores do ano no intervalo tornam-se1970-1999
.00-69
Os valores do ano no intervalo tornam-se2000-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
TIME
são cortados noTIME
intervalo 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
DATE
ou .DATETIME
Isso é ú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çõesDATE_SUB()
ouDATE_ADD()
que exigem uma data completa. Para suprimir a parte zero do mês ou do dia da data, ative esteNO_ZERO_IN_DATE
modo. -
O MySQL permite armazenar
'0000-00-00'
valores "zero" como "datas fictícias". Em alguns casos, isso éNULL
mais conveniente do que usar valores e usa menos dados e espaço de índice. Para desabilitar'0000-00-00'
, habilite esteNO_ZERO_DATE
modo. -
Os valores de data ou hora "zero" usados por meio do Connector/ODBC são convertidos automaticamente
NULL
porque 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 0
representar o valor “zero”. Usar esses valores com tipos de hora que contêm partes de data ( DATE
, DATETIME
e TIMESTAMP
) pode produzir avisos ou erros. O comportamento exato depende de NO_ZERO_DATE
qual 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 .DATETIME
TIMESTAMP
YEAR
Para descrições de intervalo de DATE
e 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 TIME
e DATETIME
valores com precisão de até microssegundos (6 dígitos). TIMESTAMP
Para definir uma coluna que contém segundos fracionários, use a sintaxe type_name
( fsp
), onde type_name
is TIME
, DATETIME
ou TIMESTAMP
, fsp
é a precisão dos segundos fracionários. Por exemplo:
CREATE TABLE t1 (t TIME(3), dt DATETIME(6), ts TIMESTAMP(0));
O fsp
valor * *, 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.)
TIMESTAMP
Qualquer coluna ou coluna em uma tabela DATETIME
pode 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-DD
formato '' DATE
, mas permite o uso de strings ou números para atribuir valores às DATE
colunas.
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 DATETIME
valores em formato, mas permite que valores sejam atribuídos a DATETIME
colunas 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 DEFAULT
as ON UPDATE
cláusulas de definição de coluna e para especificar DATETIME
a 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. TIMESTAMP
O 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_timestamp
valor de uma variável do sistema (consulte "Variáveis do sistema do servidor" ).
-
Se ativado, o atributo ou
explicit_defaults_for_timestamp
nã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_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
TIMESTAMP
TIMESTAMP
NOT NULL
NULL
-
Se
explicit_defaults_for_timestamp
desativado, o servidor trataráTIMESTAMP
isso da seguinte maneira:
A menos que especificado de outra forma, se um valor não for explicitamente atribuído à primeiraTIMESTAMP
coluna de uma Tabela, a coluna será automaticamente definida para a data e hora modificadas mais recentemente. Isso torna a coluna útilTIMESTAMP
para registrar carimbos de data/hora de operaçõesINSERT
OR .UPDATE
Você também pode definir uma coluna para a data e hora atuais atribuindo-lhe umNULL
valorTIMESTAMP
, a menos que tenha sido definido para permitirNULL
valores.
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_TIMESTAMP
e . 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_TIMESTAMP
TIMESTAMP
TIMESTAMP
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.fraction
TIME
TIME
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 YYYY
exibe YEAR
valores em formato, mas permite que valores sejam atribuídos a YEAR
colunas usando strings ou números. YEAR
Os valores são exibidos como: 1901
, 2155
ou 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 bitsYEAR(2)
em uma coluna de 4 bitsYEAR
, 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 YEAR
o 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 模式的情况下,TIMESTAMP
与DATETIME
相同。如果在创建表时启用此模式,则将TIMESTAMP
列创建为DATETIME
列。因此,此类列使用DATETIME
显示格式,具有相同的值范围,并且不会自动初始化或更新到当前日期和时间。请参阅 “服务器 SQL 模式”。自 MySQL 5.7.22 起,
MAXDB
已弃用;将在 MySQL 的未来版本中删除。
2.2 DATE、DATETIME 和 TIMESTAMP 类型
DATE
、 DATETIME
和 TIMESTAMP
类型是相关的。 本节介绍它们的特征、它们的相似之处以及它们的不同之处。MySQL 可以识别 DATE
、 DATETIME
和 TIMESTAMP
的多种格式的值,更多信息参考 “日期和时间文字” 。对于 DATE
和 DATETIME
范围描述,“ supported ”表示虽然早期的值可能有效,但不能保证。
DATE
类型用于具有日期部分但没有时间部分的值。 MySQL 以 'YYYY-MM-DD'
格式检索和显示 DATE
类型的值 。支持的范围是 '1000-01-01'
to '9999-12-31'
。
DATETIME
Tipo usado para valores que contêm componentes de data e hora. MySQL 'YYYY-MM-DD hh:mm:ss'
recupera e exibe DATETIME
valores em formato. O intervalo suportado '1000-01-01 00:00:00'
é '9999-12-31 23:59:59'
.
TIMESTAMP
Tipo usado para valores que contêm componentes de data e hora. TIMESTAMP
Tem um intervalo de '1970-01-01 00:00:01'
UTC a '2038-01-19 03:14:07'
UTC.
Um valor DATETIME
OR TIMESTAMP
pode 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 DATETIME
na coluna ou será armazenada em vez de descartada. TIMESTAMP
Depois de incluir a parte decimal, o formato desses valores é 'YYYY-MM-DD hh:mm:ss[.fraction]'
, DATETIME
digite intervalo de valores é '1000-01-01 00:00:00.000000'
para '9999-12-31 23:59:59.999999'
, TIMESTAMP
digite 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” .
TIMESTAMP
e DATETIME
os 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 TIMESTAMP
converte 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 TIMESTAMP
valor, 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_zone
uma 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 DATE
ou 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 .DATETIME
TIMESTAMP
'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, habiliteALLOW_INVALID_DATES
Para obter mais informações, consulte Modo SQL do servidor . -
O MySQL não aceita
TIMESTAMP
valores 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 eNO_ZERO_DATE
qual 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-69
tornam-se2000-2069
. - Os valores do ano no intervalo
70-99
tornam-se1970-1999
.
- Os valores do ano no intervalo
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).TIME
TIME
'-838:59:59'
'838:59:59'
TIME
O MySQL reconhece TIME
vá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, TIME
qualquer parte fracionária do valor inserido na coluna é armazenada em vez de descartada. Incluindo a parte decimal, TIME
os valores variam de '-838:59:59.000000'
até '838:59:59.000000'
.
TIME
Tenha 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, TIME
os 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 TIME
um 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
YEAR
Type é um tipo de 1 byte usado para representar valores de ano . Pode ser declarado com YEAR
uma 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 colunaYEAR(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 YYYY
exibe YEAR
valores no formato, variando de 1901
a 2155
e 0000
.
YEAR
Aceita valores de entrada em vários formatos:
-
'1901'
Uma string de 4 dígitos'2155'
no intervalo até . -
1901
para 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'
2000
2069
YEAR
'70'
'99'
1970
1999
YEAR
-
0
para 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 .1
69
2001
2069
YEAR
70
99
1970
1999
YEAR
A inserção do número
0
tem um valor exibido0000
e um valor interno de0000
. Se você deseja inserir zeros e interpretá-los2000
, especifique-os como uma string'0'
ou'00'
. -
Como
YEAR
resultado 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á YEAR
valores inválidos em 0000
.No modo SQL estrito, tentar inserir um YEAR
valor 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 YEAR
largura 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)
1901
2155
0000
YEAR(2)
YEAR(2)
YEAR
YEAR(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êsYEAR(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
y2
usará 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 interno2012
e um valor exibido de12
, perdendo assim a distinção entre elas. -
Converte um valor de dados de 2 ou 4 dígitos
YEAR
em formato de string usando seu tipo de dados para exibir a largura. Suponha que umaYEAR(2)
coluna e uma colunaYEAR
/YEAR(4)
contenham1970
valores. 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
CSV
de uma tabelaYEAR(2)
, valores fora do intervalo1970
to2069
são armazenados incorretamente. Por exemplo, a inserção2211
resultaria em um valor exibido de11
, mas em um valor interno de2011
.
YEAR
Para 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
TIMESTAMP
e DATETIME
as colunas podem ser inicializadas e atualizadas automaticamente para a data e hora atuais (ou seja, o carimbo de data/hora atual).
TIMESTAMP
Para 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_timestamp
atribuindo-lhe um valor , a menos que tenha sido definido para permitir um valor.TIMESTAMP
DATETIME
NULL
NULL
Para especificar propriedades automáticas, use DEFAULT CURRENT_TIMESTAMP
as ON UPDATE CURRENT_TIMESTAMP
clá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_TIMESTAMP
Quaisquer sinônimos para CURRENT_TIMESTAMP
têm o mesmo significado que . Eles são CURRENT_TIMESTAMP()
, NOW()
, LOCALTIME
, LOCALTIME()
, LOCALTIMESTAMP
e 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.3 Tipos BINÁRIOS e VARBINÁRIOS
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.3 Formatos de dados espaciais suportados
4.4 Boa formação geométrica e validade
4.6 Preenchendo colunas espaciais
4.7 Obtenção de dados espaciais
4.8 Análise espacial de otimização
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
JSON
documentos JSON armazenados em colunas. Documentos inválidos geram erros. - Formato de armazenamento otimizado. Os documentos JSON armazenados
JSON
em 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.
JSON
O espaço necessário para armazenar um documento é aproximadamente o mesmo que LONGBLOB
ou 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_packet
valor 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 JSON
não podem ter NULL
valores não padrão.
Além dos JSON
tipos 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 .
JSON
As 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 JSON
extrair 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 JSON
geradas a partir de colunas como uma solução alternativa para colunas que não podem ser indexadas. Cada tabela suporta até 3 colunas.JSON
JSON
NDB
JSON
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 JSON
digitar. 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 JSON
colunas com tipos de dados e a passagem de argumentos para funções que esperam valores JSON (geralmente mostrados como * json_doc
ou * json_val
na documentação das funções JSON do MySQL), conforme mostrado no exemplo a seguir:
JSON
Uma 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
为。(对于ascii
orutf8
字符集中的字符串,不需要转换,因为ascii
andutf8
是utf8mb4
的子集。)
说明(自己补充)
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 JSON
um tipo de dados, portanto, embora @j
pareç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 JSON
tipo 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 longtext
tipo).
A string gerada pela conversão de um valor JSON possui um conjunto de caracteres utf8mb4
e um agrupamento utf8mb4_bin
:
mysql> SELECT CHARSET(@j), COLLATION(@j);
+-------------+---------------+
| CHARSET(@j) | COLLATION(@j) |
+-------------+---------------+
| utf8mb4 | utf8mb4_bin |
+-------------+---------------+
Por utf8mb4_bin
ser 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 null
e true
caracteres 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 NULL
e TRUE
dos FALSE
caracteres, 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 mascot
frase 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. SeJSON_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 key1
elemento 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. name
Por 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 imediatamentepath
significa selecionar um elementopath
com 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 :N
N
path
path
path
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**suffix
Conta todos os caminhosprefix
começ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 como3
.$[1]
Avaliado como{"a": [5, 6], "b": 10}
.$[2]
Avaliado como[99, 100]
.$[3]
Avalia comoNULL
(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].a
Avaliado como[5, 6]
.$[1].a[1]
Avaliado como6
.$[1].b
Avaliado como10
.$[2][0]
Avaliado como99
.
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 comoshark
.$."a bird"
Avaliado comosparrow
.
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 $**.b
avalia vários caminhos ( $.a.b
sum $.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->path
identificadores 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]
correspondeb
ao elementofalse
e 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
, utf8
ou . utf8mb4
Outras 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]**suffix
Representa todos os caminhosprefix
começando e terminando com . é opcional, mas obrigatório; em outras palavras, o caminho não pode terminar em .suffix
prefix
suffix
**
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
N
Compara os primeiros bytes de dois valores , ondeN
é o número de bytes no valor mais curto. Se os primeirosN
bytes de dois valores forem iguais, o valor mais curto será classificado antes do valor mais longo. -
BIT
BLOB
Mesmas regras do . -
OPAQUE
BLOB
Mesmas regras do .OPAQUE
Type é 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
DATETIME
eTIMESTAMP
do 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
utf8mb4
primeiros 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.N
N
N
exemplo:
"a" < "ab" < "b" < "bc"
Essa classificação é equivalente a usar
utf8mb4_bin
agrupamento para classificar strings SQL. Por causautf8mb4_bin
do 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
INT
eDOUBLE
tipos 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 NULL
comparaçã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 utf8mb4 strings. |
Outros tipos de caracteres | Outras codificações de caracteres são convertidas implicitamente em utf8mb4 tipos de caracteres e processadas de acordo com o conjunto de caracteres utf8. |
Os valores JSON são serializados em utf8mb4 strings e depois convertidos em outras codificações de caracteres. Os resultados podem não fazer sentido. |
NULL |
Retorna NULL um 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 NULL e gere um aviso. |
Para valores JSON ORDER BY
e GROUP BY
funciona 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
NULL
são classificados antes de todos os valores JSON, incluindo literais JSON NULL; para classificação descendente, os SQL sãoNULL
classificados depois de todos os valores JSON, incluindo literais JSON NULL. - A chave de classificação de um valor JSON é limitada pelo
max_sort_length
valor de uma variável do sistema, portantomax_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、相关参考:
第 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 BLOB
as colunas OR TEXT
, que representam apenas 9 a 12 bytes deste tamanho. Para dados BLOB
e 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 InnoDB
os 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 |
DECIMAL
Os 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
, DATETIME
e 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 开始,存储 YEAR
和 DATE
保持不变。但是, TIME
、 DATETIME
和 TIMESTAMP
的表示方式不同。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) 个字节。TIME
与 TIME(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
*字节来存储值加上三个字节来存储值的长度。
要计算用于存储特定 CHAR
、 VARCHAR
或 TEXT
列值的字节数,您必须考虑用于该列的字符集以及该值是否包含多字节字符。特别是,在使用 utf8
Unicode 字符集时,您必须牢记并非所有字符都使用相同的字节数。utf8mb3
和 utf8mb4
字符集每个字符最多分别需要三个和四个字节。有关用于不同类别 utf8mb3
或 utf8mb4
字符的存储细分,请参阅 第 10.9 节,“Unicode 支持”。
VARCHAR
, VARBINARY
, BLOB
和 TEXT
类型是变长类型。对于它们的每个,存储要求取决于以下因素:
- 列值的实际长度
- 列的最大可能长度
- 列使用的字符集,因为有些字符集包含多字节字符
例如,一个 VARCHAR(255)
列可以包含最大长度为 255 个字符的字符串。假设该列使用latin1
字符集(每个字符一个字节),实际需要的存储是字符串的长度(L
),加上一个字节来记录字符串的长度。对于字符串 'abcd'
,*L
*是 4 并且存储要求是 5 个字节。如果同一列改为使用ucs2
双字节字符集,则存储要求为 10 个字节: 'abcd'
的长度为 8 个字节,该列需要两个字节来存储长度,因为最大长度大于 255(最多 510字节)。
一个 VARCHAR
或 VARBINARY
列中可以存储的最大有效字节数取决于最大行大小 65,535 字节,该最大行大小在所有列之间共享。对于存储多字节字符的 VARCHAR
列,最大有效字符数较少。例如, utf8mb3
的每个字符最多需要三个字节,因此可以将使用 utf8mb3
字符集的 VARCHAR
列声明为最多 21,844 个字符。请参阅 第 8.4.7 节,“表列数和行大小的限制”。
InnoDB
将长度大于或等于 768 字节的固定长度字段编码为可变长度字段,可以在页外存储。例如, CHAR(255)
如果字符集的最大字节长度大于 3,则列可以超过 768 个字节,就像utf8mb4
。
NDB
存储引擎支持可变宽度列 。这意味着 VARCHAR
NDB 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
列的存储要求与 LONGBLOB
或 LONGTEXT
列的存储要求大致相同;也就是说,JSON 文档占用的空间与存储在其中一种类型的列中的文档字符串表示所占用的空间大致相同。但是,存储在 JSON 文档中的各个值的二进制编码(包括查找所需的元数据和字典)会产生开销。例如,存储在 JSON 文档中的字符串需要 4 到 10 个字节的额外存储空间,具体取决于字符串的长度以及存储它的对象或数组的大小。
此外,MySQL 对存储在JSON
列中的任何 JSON 文档的大小施加了限制,使其不能大于 max_allowed_packet
.