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.