Mistura ilegal de agrupamentos MySQL Error


124

Estou recebendo esse erro estranho ao processar um grande número de dados ...

Error Number: 1267

Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '='

SELECT COUNT(*) as num from keywords WHERE campaignId='12' AND LCASE(keyword)='hello again 昔 ã‹ã‚‰ ã‚ã‚‹ å ´æ‰€'

O que posso fazer para resolver isso? Posso escapar da string de alguma forma para que esse erro não ocorra ou preciso alterar a codificação da minha tabela de alguma forma? Em caso afirmativo, para que devo alterá-la?


esse erro, é injetável ou não?
— Hamza irizaj

Respostas:


288
SET collation_connection = 'utf8_general_ci';

então para seus bancos de dados

ALTER DATABASE your_database_name CHARACTER SET utf8 COLLATE utf8_general_ci;

ALTER TABLE your_table_name CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

O MySQL foge sueco algumas vezes sem nenhuma razão sensata.


3
@ Ben: Obrigado por uma solução diretamente copiável e colável. Me salvou muito tempo.
— Pistos

15
@ Ben: Ele foi inicialmente desenvolvido por uma empresa sueca ... Essa é a razão por trás da definição inicial latin1_swedish_ci chato .. :(
— Vajk Hermecz

1
Eu não tinha permissão para fazer a primeira declaração, mas funcionou apenas fazendo a mesa
— Rob Sedgwick

Te amo por isso! : P
— prateekkathal

Parece que isso funciona para muitas pessoas, mas infelizmente ainda tenho esse problema, mesmo depois de experimentar todo o dispositivo deste segmento. Meu agrupamento padrão do banco de dados teimosamente se recusa a mudar de 'ucs2_bin', então até tentei alterar todas as tabelas e o agrupamento de conexões para 'usc2_bin', mas ainda recebo o erro "Erro SQL (1267): mistura ilegal de agrupamentos (utf8_general_ci, IMPLICIT) e (ucs2_bin, IMPLICIT) para a operação '=' ".
— bikeman868

15

Você deve definir sua codificação de tabela e codificação de conexão para UTF-8:

ALTER TABLE keywords CHARACTER SET UTF8; -- run once

e

SET NAMES 'UTF8';
SET CHARACTER SET 'UTF8';

Ambos são necessários ou posso apenas executar um deles?
— Click Upvote

ALTER DATABASE myDbPADRÃO PERSONALIZADO SET utf8 COLLATE utf8_bin. Isso funcionaria? Isso é feito para que todas as minhas tabelas sejam afetadas, e não apenas uma delas.
— Click Upvote

1
O ALTER DATABASE não altera as configurações atuais da tabela, apenas as recém-criadas. Porém, não fará mal alterar também o conjunto de caracteres padrão para o banco de dados.
— Quassnoi

SET NAMES e SET CHARACTER SET mudam a codificação da sua conexão. Você precisa emitir esses comandos sempre que se conectar. Sua biblioteca cliente pode suportar um método mais elegante para fazer isso (php :: mysqli suporta, php :: mysql não suporta).
— Quassnoi

Parece funcionar por enquanto, vou aceitar depois de mais alguns testes. As segundas consultas precisam ser executadas uma vez ou no início de cada script?
— Click Upvote

13
CONVERT(column1 USING utf8)

Resolve meu problema. Onde column1 é a coluna que me dá esse erro.


Para mim, isso funcionou: CONVERT ("column1" USANDO LATIN1)
— shasi kanth

4

Use a seguinte instrução para erro

tenha cuidado com seus dados, faça backup se houver dados na tabela.

 ALTER TABLE your_table_name CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

2

Em geral, a melhor maneira é alterar o agrupamento da tabela. No entanto, tenho um aplicativo antigo e não sou capaz de estimar o resultado se isso tem efeitos colaterais. Portanto, tentei de alguma forma converter a string em outro formato que resolvesse o problema de agrupamento. O que eu achei trabalhando é fazer a comparação de cadeias, convertendo as cadeias em uma representação hexadecimal de seus caracteres. No banco de dados, isso é feito com o HEX(column).PHP, você pode usar esta função:

public static function strToHex($string)
{
    $hex = '';
    for ($i=0; $i<strlen($string); $i++){
        $ord = ord($string[$i]);
        $hexCode = dechex($ord);
        $hex .= substr('0'.$hexCode, -2);
    }
    return strToUpper($hex);
}

Ao fazer a consulta ao banco de dados, sua string UTF8 original deve ser convertida primeiro em uma string iso (por exemplo, usando utf8_decode()no PHP) antes de usá-la no banco de dados. Devido ao tipo de intercalação, o banco de dados não pode ter caracteres UTF8, portanto o comparismo deve funcionar, embora isso altere a cadeia original (a conversão de caracteres UTF8 que não existem no conjunto de caracteres ISO resulta em? Ou estes são removidos completamente). Apenas certifique-se de que, ao gravar dados no banco de dados, use a mesma conversão UTF8 em ISO.


2

Minha tabela foi criada originalmente com CHARSET = latin1 . Após a conversão da tabela para utf8, algumas colunas não foram convertidas, no entanto, isso não era realmente óbvio. Você pode tentar executar SHOW CREATE TABLE my_table;e ver qual coluna não foi convertida ou apenas corrigir o conjunto de caracteres incorreto na coluna problemática com a consulta abaixo (altere o comprimento do varchar e CHARSET e COLLATE de acordo com suas necessidades):

 ALTER TABLE `my_table` CHANGE `my_column` `my_column` VARCHAR(10) CHARSET utf8 
 COLLATE utf8_general_ci NULL;

2

Altere o conjunto de caracteres da tabela para utf8

ALTER TABLE your_table_name CONVERT TO CHARACTER SET utf8


0

Depois de fazer as correções listadas na resposta superior, altere as configurações padrão do seu servidor.

No seu " /etc/my.cnf.d/server.cnf " ou em qualquer outro local, adicione os padrões à seção [mysqld] para que fique assim:

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

Fonte: https://dev.mysql.com/doc/refman/5.7/en/charset-applications.html


0

Eu descobri que usar cast()era a melhor solução para mim:

cast(Format(amount, "Standard") AS CHAR CHARACTER SET utf8) AS Amount

Há também uma convert()função. Mais detalhes aqui

Outro recurso aqui


0

Minha conta de usuário não tinha permissões para alterar o banco de dados e a tabela, conforme sugerido nesta solução .

Se, como eu, você não se importar com o agrupamento de caracteres (você está usando o operador '='), poderá aplicar a correção inversa. Execute isso antes do seu SELECT:

SET collation_connection = 'latin1_swedish_ci';
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.