Estou recebendo o erro abaixo ao tentar fazer uma seleção através de um procedimento armazenado no MySQL.
Mistura ilegal de agrupamentos (latin1_general_cs, IMPLICIT) e (latin1_general_ci, IMPLICIT) para a operação '='
Alguma idéia do que pode estar errado aqui?
O agrupamento da tabela é latin1_general_ci
e o da coluna na cláusula where latin1_general_cs
.
Respostas:
Isso geralmente é causado pela comparação de duas cadeias de agrupamento incompatível ou pela tentativa de selecionar dados de agrupamento diferente em uma coluna combinada.
A cláusula
COLLATE
permite especificar o agrupamento usado na consulta.Por exemplo, a seguinte
WHERE
cláusula sempre fornecerá o erro que você postou:Sua solução é especificar um agrupamento compartilhado para as duas colunas na consulta. Aqui está um exemplo que usa a
COLLATE
cláusula:Outra opção é usar o
BINARY
operador:Sua solução pode ser algo como isto:
ou,
fonte
COLLATE latin1_general_ci
que causa outro erro:COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'latin1''
- mesmo se você não tiver uma coluna com CHARACTER SET 'latin1'! A solução é usar o elenco BINARY. Veja também esta perguntaTL; DR
Altere o agrupamento de uma (ou ambas) das seqüências para que correspondam ou adicione uma
COLLATE
cláusula à sua expressão.O que é esse material de "agrupamento", afinal?
Conforme documentado em Conjuntos de caracteres e agrupamentos em geral :
Outros exemplos são dados em Exemplos do efeito de agrupamento .
Ok, mas como o MySQL decide qual agrupamento usar para uma determinada expressão?
Conforme documentado em Agrupamento de expressões :
Então, o que é uma "mistura ilegal de agrupamentos"?
Uma "mistura ilegal de agrupamentos" ocorre quando uma expressão compara duas cadeias de agrupamentos diferentes, mas de igual coerência e as regras de coerção não podem ajudar a resolver o conflito. É a situação descrita no terceiro ponto da citação acima.
O erro específico fornecido na pergunta,
Illegal mix of collations (latin1_general_cs,IMPLICIT) and (latin1_general_ci,IMPLICIT) for operation '='
diz-nos que houve uma comparação de igualdade entre duas seqüências não-Unicode de igual coercibilidade. Além disso, nos diz que os agrupamentos não foram fornecidos explicitamente na declaração, mas foram implícitos nas fontes das strings (como metadados da coluna).Tudo muito bem, mas como se resolve esses erros?
Como sugerem os extratos do manual citados acima, esse problema pode ser resolvido de várias maneiras, das quais duas são sensíveis e recomendadas:
Altere o agrupamento de uma (ou de ambas) das seqüências de caracteres para que correspondam e não exista mais ambiguidade.
Como isso pode ser feito depende de onde a string veio: Expressões literais recebem o agrupamento especificado na
collation_connection
variável do sistema; os valores das tabelas recebem o agrupamento especificado em seus metadados da coluna.Force uma sequência a não ser coercível.
Omiti a seguinte citação do acima exposto:
Assim, simplesmente adicionar uma
COLLATE
cláusula a uma das strings usadas na comparação forçará o uso desse agrupamento.Enquanto os outros seriam uma péssima prática se eles fossem implantados apenas para resolver este erro:
Forçar uma (ou ambas) das seqüências de caracteres a ter algum outro valor de coercibilidade, para que uma tenha precedência.
O uso de
CONCAT()
ouCONCAT_WS()
resultaria em uma string com uma coercibilidade de 1; e (se em uma rotina armazenada) o uso de parâmetros / variáveis locais resultaria em seqüências de caracteres com uma coercibilidade de 2.Altere as codificações de uma (ou de ambas) das seqüências de caracteres para que uma seja Unicode e a outra não.
Isso pode ser feito via transcodificação com ; ou via alteração do conjunto de caracteres subjacente dos dados (por exemplo, modificação da coluna, alteração de valores literais ou envio do cliente em uma codificação diferente e alteração / adição de um introdutor de conjunto de caracteres). Observe que a alteração da codificação levará a outros problemas se alguns caracteres desejados não puderem ser codificados no novo conjunto de caracteres.
CONVERT(expr USING transcoding_name)
character_set_connection
character_set_client
Altere as codificações de uma (ou ambas) das seqüências de caracteres para que elas sejam as mesmas e altere uma sequência para usar o
_bin
agrupamento relevante .Os métodos para alterar codificações e agrupamentos foram detalhados acima. Essa abordagem seria de pouca utilidade se alguém realmente precisasse aplicar regras de agrupamento mais avançadas do que as oferecidas pelo
_bin
agrupamento.fonte
Adicionando meu 2c à discussão para futuros googlers.
Eu estava investigando um problema semelhante no qual obtive o seguinte erro ao usar funções personalizadas que receberam um parâmetro varchar:
Usando a seguinte consulta:
Consegui dizer que o banco de dados estava usando utf8_general_ci , enquanto as tabelas foram definidas usando utf8_unicode_ci :
Observe que as visualizações têm agrupamento NULL . Parece que as visualizações e funções têm definições de agrupamento, embora essa consulta mostre nulo para uma visualização. O agrupamento usado é o agrupamento de banco de dados que foi definido quando a exibição / função foi criada.
A solução triste foi alterar o agrupamento de banco de dados e recriar as visualizações / funções para forçá-los a usar o agrupamento atual.
Alterando o agrupamento do banco de dados:
Alterando o agrupamento da tabela:
Espero que isso ajude alguém.
fonte
show full columns from my_table;
alter table <TABLE> modify column <COL> varchar(255) collate utf8_general_ci;
SHOW session variables like '%collation%';
diz que »collation_connection« é »utf8mb4_general_ci«? Então corra deSET collation_connection = utf8mb4_unicode_ci
antemão.Às vezes, pode ser perigoso converter conjuntos de caracteres, especialmente em bancos de dados com grandes quantidades de dados. Eu acho que a melhor opção é usar o operador "binário":
fonte
Eu tive um problema semelhante, estava tentando usar o procedimento FIND_IN_SET com uma variável de string .
e estava recebendo o erro
Resposta curta:
Não é necessário alterar nenhuma variável collation_YYYY; basta adicionar o agrupamento correto ao lado da sua declaração de variável , ou seja,
Resposta longa:
Primeiro verifiquei as variáveis de agrupamento:
Depois verifiquei o agrupamento da tabela:
Isso significa que minha variável foi configurada com o agrupamento padrão de utf8_general_ci enquanto minha tabela foi configurada como utf8_unicode_ci .
Ao adicionar o comando COLLATE ao lado da declaração da variável, o agrupamento da variável correspondeu ao agrupamento configurado para a tabela.
fonte
Você pode tentar este script , que converte todos os seus bancos de dados e tabelas em utf8.
fonte
Solução se literais estiverem envolvidos.
Estou usando o Pentaho Data Integration e não consigo especificar a sintaxe sql. O uso de uma pesquisa de banco de dados muito simples deu o erro "Mistura ilegal de agrupamentos (cp850_general_ci, COERCIBLE) e (latin1_swedish_ci, COERCIBLE) para a operação '='"
O código gerado foi "SELECT DATA_DATE AS latest_DATA_DATE FROM hr_cc_normalised_data_date_v WHERE PSEUDO_KEY =?"
Para resumir a história, a pesquisa foi vista e quando eu publiquei
que explica de onde vem o 'cp850_general_ci'.
A visualização foi simplesmente criada com 'SELECT' X ', ......' De acordo com o manual, literais como este devem herdar seu conjunto de caracteres e agrupamento das configurações do servidor definidas corretamente como 'latin1' e 'latin1_general_cs' como este claramente não aconteceu eu forcei na criação da visão
agora mostra latin1_general_cs para ambas as colunas e o erro desapareceu. :)
fonte
O MySQL realmente não gosta de misturar agrupamentos, a menos que possa coagi-los ao mesmo (o que claramente não é viável no seu caso). Você não pode simplesmente forçar o mesmo agrupamento a ser usado por meio de uma cláusula COLLATE ? (ou o
BINARY
atalho mais simples, se aplicável ...).fonte
Se as colunas com as quais você está tendo problemas são "hashes", considere o seguinte ...
Se o "hash" for uma string binária, você realmente deve usar o
BINARY(...)
tipo de dados.Se o "hash" for uma sequência hexadecimal, você não precisa de utf8 e deve evitá-lo devido a verificações de caracteres etc. Por exemplo, o MySQL
MD5(...)
produz uma sequência hexadecimal de 32 bytes de comprimento fixo.SHA1(...)
fornece uma cadeia hexadecimal de 40 bytes. Isso pode ser armazenado emCHAR(32) CHARACTER SET ascii
(ou 40 para sha1).Ou, ainda melhor, armazenar
UNHEX(MD5(...))
emBINARY(16)
. Isso corta pela metade o tamanho da coluna. (No entanto, torna-o bastante imprimível.)SELECT HEX(hash) ...
Se você quiser que seja legível.A comparação de duas
BINARY
colunas não apresenta problemas de agrupamento.fonte
Muito interessante ... Agora, esteja pronto. Eu olhei para todas as soluções "adicionar agrupar" e para mim, essas são correções de band-aid. A realidade é que o design do banco de dados era "ruim". Sim, alterações padrão e coisas novas são adicionadas, blá, blá, mas isso não altera o fato ruim de design do banco de dados. Recuso-me a seguir a rota de adicionar "agrupar" em todas as instruções SQL apenas para fazer minha consulta funcionar. A única solução que funciona para mim e praticamente elimina a necessidade de ajustar meu código no futuro é redesenhar o banco de dados / tabelas para corresponder ao conjunto de caracteres com o qual viverei e adotarei no futuro a longo prazo. Nesse caso, optei por usar o conjunto de caracteres " utf8mb4 ".
Portanto, a solução aqui quando você encontrar essa mensagem de erro "ilegal" é redesenhar seu banco de dados e tabelas. É muito mais fácil e rápido do que parece. Exportar seus dados e reimportá-los de um CSV pode até não ser necessário. Altere o conjunto de caracteres do banco de dados e verifique se todo o conjunto de caracteres de suas tabelas corresponde.
Use estes comandos para guiá-lo:
Agora, se você gosta de adicionar "agrupar" aqui e ali e aprimorar seu código com "substituições" de forças, seja meu palpite.
fonte
Uma solução possível é converter o banco de dados inteiro em UTF8 (consulte também esta pergunta ).
fonte
Outra fonte do problema de agrupamentos é a
mysql.proc
tabela. Verifique agrupamentos de seus procedimentos e funções de armazenamento:Também preste atenção
mysql.proc.collation_connection
emysql.proc.character_set_client
colunas.fonte
Se você tiver o phpMyAdmin instalado, poderá seguir as instruções fornecidas no seguinte link: https://mediatemple.net/community/products/dv/204403914/default-mysql-character-set-and-collation Você deve corresponder ao agrupamento do banco de dados com o de todas as tabelas, bem como os campos das tabelas e recompile todos os procedimentos e funções armazenados. Com isso tudo deve funcionar novamente.
fonte
eu usei
ALTER DATABASE mydb DEFAULT COLLATE utf8_unicode_ci;
, mas não funcionou.Nesta consulta:
Este trabalho para mim:
Sim, apenas a
concat
.fonte
Esse código precisa ser colocado dentro de Executar consultas / consultas SQL no banco de dados
JANELA DE CONSULTA SQL
Substitua table_name e column_name pelo nome apropriado.
fonte