Eu tenho uma tabela com uma chave primária que é um varchar (255). Alguns casos surgiram onde 255 caracteres não são suficientes. Tentei alterar o campo para um texto, mas recebo o seguinte erro:
BLOB/TEXT column 'message_id' used in key specification without a key length
Como posso consertar isso?
editar: devo também apontar que esta tabela possui uma chave primária composta com várias colunas.
mysql
sql
mysql-error-1170
GSto
fonte
fonte
UNIQUE
chaves?Respostas:
O erro ocorre porque o MySQL pode indexar apenas os primeiros N caracteres de um BLOB ou
TEXT
coluna. Assim, o erro acontece principalmente quando há um tipo de campo / colunaTEXT
ou BLOB ou aqueles pertencemTEXT
ouBLOB
tipos, tais comoTINYBLOB
,MEDIUMBLOB
,LONGBLOB
,TINYTEXT
,MEDIUMTEXT
, eLONGTEXT
que você tenta fazer uma chave primária ou índice. Com o valor totalBLOB
ouTEXT
sem o comprimento, o MySQL não pode garantir a exclusividade da coluna, pois é de tamanho variável e dinâmico. Portanto, ao usarBLOB
ouTEXT
digitar como índice, o valor de N deve ser fornecido para que o MySQL possa determinar o comprimento da chave. No entanto, o MySQL não suporta um limite de tamanho de chave emTEXT
ouBLOB
.TEXT(88)
simplesmente não vai funcionar.O erro também aparecerá quando você tentar converter uma coluna da tabela
non-TEXT
enon-BLOB
digitar comoVARCHAR
eENUM
paraTEXT
ouBLOB
digite, com a coluna já definida como restrições ou índices exclusivos. O comando Alterar tabela SQL falhará.A solução para o problema é remover a coluna
TEXT
ouBLOB
do índice ou restrição exclusiva ou definir outro campo como chave primária. Se você não puder fazer isso, e quiser colocar um limite na colunaTEXT
ouBLOB
, tente usar oVARCHAR
tipo e coloque um limite de comprimento nela. Por padrão,VARCHAR
é limitado a um máximo de 255 caracteres e seu limite deve ser especificado implicitamente dentro de um colchete logo após a declaração, ou sejaVARCHAR(200)
, o limite será de apenas 200 caracteres.Às vezes, mesmo que você não use
TEXT
ouBLOB
tipo relacionado na sua tabela, o Erro 1170 também pode aparecer. Isso acontece em uma situação como quando você especificaVARCHAR
coluna como chave primária, mas define incorretamente seu tamanho ou tamanho de caracteres.VARCHAR
só pode aceitar até 256 caracteres, portanto, qualquer coisa queVARCHAR(512)
forçará o MySQL a converter automaticamenteVARCHAR(512)
para umSMALLTEXT
tipo de dados, que subsequentemente falhará com o erro 1170 no comprimento da chave se a coluna for usada como chave primária ou índice único ou não exclusivo. Para resolver esse problema, especifique um valor menor que 256 como o tamanho doVARCHAR
campo.Referência: Erro MySQL 1170 (42000): Coluna BLOB / TEXT Usada na Especificação de Chaves Sem um Comprimento de Chave
fonte
Você deve definir qual parte principal de uma
TEXT
coluna você deseja indexar.InnoDB
tem uma limitação de768
bytes por chave de índice e você não poderá criar um índice por mais tempo que isso.Isso funcionará bem:
Observe que o valor máximo do tamanho da chave depende do conjunto de caracteres da coluna. São
767
caracteres para um conjunto de caracteres de byteLATIN1
único e somente255
caracteres paraUTF8
(MySQL
apenas usosBMP
que requerem no máximo3
bytes por caractere)Se você precisar que sua coluna inteira seja a
PRIMARY KEY
, calculeSHA1
ouMD5
use hash e use-a como aPRIMARY KEY
.fonte
REDUNDANT
ouCOMPACT
linha. Por exemplo, você pode atingir esse limite com um índice de prefixo de coluna com mais de 255 caracteres em umaTEXT
ouVARCHAR
coluna, assumindo um conjunto de caracteres utf8mb3 e o máximo de 3 bytes para cada caractere.REDUNDANT
eCOMPACT
eram os únicos formatos disponíveis no momento em que essa resposta foi dada.Você pode especificar o comprimento da chave na solicitação de alteração da tabela, algo como:
fonte
Não permite a MySQL indexação de um valor total
BLOB
,TEXT
e longasVARCHAR
colunas porque os dados que eles contêm podem ser enormes, e implicitamente índice DB será grande, o que significa que nenhum benefício a partir do índice.O MySQL exige que você defina os primeiros N caracteres a serem indexados, e o truque é escolher um número N que seja longo o suficiente para oferecer boa seletividade, mas curto o suficiente para economizar espaço. O prefixo deve ser longo o suficiente para tornar o índice quase tão útil quanto seria se você tivesse indexado a coluna inteira.
Antes de avançarmos, vamos definir alguns termos importantes. A seletividade do índice é a proporção do total de valores indexados distintos e do número total de linhas . Aqui está um exemplo para a tabela de teste:
Se indexarmos apenas o primeiro caractere (N = 1), a tabela de índice será semelhante à seguinte:
Nesse caso, a seletividade do índice é igual a IS = 1/3 = 0,33.
Vamos agora ver o que acontecerá se aumentarmos o número de caracteres indexados para dois (N = 2).
Nesse cenário, IS = 2/3 = 0,66, o que significa que aumentamos a seletividade do índice, mas também aumentamos o tamanho do índice. O truque é encontrar o número mínimo N que resultará na seletividade máxima do índice .
Existem duas abordagens que você pode fazer cálculos para sua tabela de banco de dados. Farei uma demonstração no despejo deste banco de dados .
Digamos que queremos adicionar a coluna last_name nos funcionários da tabela ao índice e queremos definir o menor número N que produzirá a melhor seletividade do índice.
Primeiro, vamos identificar os sobrenomes mais frequentes:
Como você pode ver, o sobrenome Baba é o mais frequente. Agora, vamos encontrar os prefixos last_name mais frequentes , começando com prefixos de cinco letras.
Há muito mais ocorrências de cada prefixo, o que significa que precisamos aumentar o número N até que os valores sejam quase os mesmos que no exemplo anterior.
Aqui estão os resultados para N = 9
Aqui estão os resultados para N = 10.
São resultados muito bons. Isso significa que podemos criar um índice na coluna
last_name
indexando apenas os 10 primeiros caracteres. Na definição da tabela, colunalast_name
é definida comoVARCHAR(16)
, e isso significa que salvamos 6 bytes (ou mais, se houver caracteres UTF8 no sobrenome) por entrada. Nesta tabela, existem 1637 valores distintos multiplicados por 6 bytes e cerca de 9 KB, e imagine como esse número aumentaria se nossa tabela contivesse milhões de linhas.Você pode ler outras maneiras de calcular o número de N em meus índices pré-fixados no MySQL .
fonte
Eu recebi esse erro ao adicionar um índice a uma tabela com colunas de tipo de texto. Você precisa declarar a quantidade de tamanho que deseja usar para cada tipo de texto.
Coloque a quantidade de tamanho entre parênteses ()
Se forem usados muitos bytes, você poderá declarar um tamanho entre colchetes para varchar para diminuir a quantidade usada para indexação. Isso ocorre mesmo se você tiver declarado um tamanho para um tipo que já seja como varchar (1000). Você não precisa criar uma nova tabela como outras pessoas disseram.
Adicionando índice
Adicionando índice exclusivo
fonte
NOTA : 767 é o número de caracteres limite até o qual o MySQL indexará colunas enquanto lida com índices de blob / texto
Ref: http://dev.mysql.com/doc/refman/5.7/en/innodb-restrictions.html
fonte
Outra excelente maneira de lidar com isso é criar seu campo TEXT sem a restrição exclusiva e adicionar um campo irmão VARCHAR exclusivo e que contém um resumo (MD5, SHA1 etc.) do campo TEXT. Calcule e armazene o resumo sobre todo o campo TEXTO quando você insere ou atualiza o campo TEXTO; então, há uma restrição de exclusividade sobre todo o campo TEXTO (em vez de uma parte principal) que pode ser pesquisada rapidamente.
fonte
Não tenha valores longos como chave primária. Isso destruirá seu desempenho. Veja o manual do mysql, seção 13.6.13 'Ajuste e solução de problemas do desempenho do InnoDB'.
Em vez disso, tenha uma chave int substituta como primária (com incremento automático) e sua chave longa como uma UNIQUE secundária.
fonte
Adicione outra coluna varChar (255) (com o padrão como sequência vazia e não nula) para manter o estouro quando 255 caracteres não forem suficientes e altere esse PK para usar as duas colunas. No entanto, isso não parece um esquema de banco de dados bem projetado, e eu recomendaria que um modelador de dados analisasse o que você tem com o objetivo de refatorá-lo para obter mais Normalização.
fonte
A solução para o problema é que, em sua
CREATE TABLE
declaração, você pode adicionar a restriçãoUNIQUE ( problemtextfield(300) )
após a coluna criar definições para especificar umkey
comprimento de300
caracteres para umTEXT
campo, por exemplo. Em seguida, os primeiros300
caracteres doproblemtextfield
TEXT
campo precisariam ser exclusivos e quaisquer diferenças posteriores a isso seriam desconsideradas.fonte
Além disso, se você quiser usar o índice nesse campo, use o mecanismo de armazenamento MyISAM e o tipo de índice FULLTEXT.
fonte
Ninguém o mencionou até agora ... com utf8mb4, que tem 4 bytes e também pode armazenar emoticons (nunca devemos usar utf8 de 3 bytes) e podemos evitar erros
Incorrect string value: \xF0\x9F\x98\...
, pois não devemos usar o VARCHAR típico (255), mas sim o VARCHAR ( 191) porque no caso utf8mb4 e VARCHAR (255) a mesma parte dos dados é armazenada fora da página e você não pode criar um índice para a coluna VARCHAR (255), mas para VARCHAR (191) é possível. Isso ocorre porque o tamanho máximo da coluna indexada é de 767 bytes para ROW_FORMAT = COMPACT ou ROW_FORMAT = REDUNDANT.Para formatos de linha mais recentes ROW_FORMAT = DYNAMIC ou ROW_FORMAT = COMPRESSED (o que requer um formato de arquivo mais recente innodb_file_format = Barracuda não é mais antigo Antelope) o tamanho máximo da coluna indexada é 3072. Está disponível desde o MySQL> = 5.6.3 quando innodb_large_prefix = 1 (desativado por padrão MySQL <= 5.7.6 e ativado por padrão para MySQL> = 5.7.7). Portanto, neste caso, podemos usar VARCHAR (768) para utf8mb4 (ou VARCHAR (1024) para utf8 antigo) para coluna indexada. A opção innodb_large_prefix está obsoleta desde 5.7.7 porque seu comportamento está embutido no MySQL 8 (nesta versão a opção foi removida).
fonte
Você precisa alterar o tipo de coluna para
varchar
ouinteger
para indexação.fonte
Vá para mysql
edit table
-> altere o tipo de coluna paravarchar(45)
.fonte
Use assim
fonte