Adicionando nova collation no MySQL

Eu sou do tipo de DBA que prefere manter as coisas mais simples possíveis, mas, tem vezes em que não é possível. Alguns dias atrás, me deparei com um problema no qual, nenhuma das collations presentes no MySQL iria garantir a integridade do meu banco de dados, e para evitar uma grande re-escrita do código fonte, me deparei com uma opção até então desconhecida.
Adicionar minha própria collation no MySQL

Esta opção está descrita nesta sessão da documentação.
Neste artigo, vou mostrar como fazer o MySQL identificar vogais com acento agudo como uma letra diferente.

Primeiro, precisamos descobrir onde está o nosso diretório com os charset’s:


mysql [localhost] {msandbox} ((none)) > SHOW VARIABLES LIKE 'character_sets_dir';
+--------------------+---------------------------------------+
| Variable_name | Value |
+--------------------+---------------------------------------+
| character_sets_dir | /mysql/sources/5.6.26/share/charsets/ |
+--------------------+---------------------------------------+
1 row in set (0.00 sec)

Neste caso, vou estar trabalhando com a pasta /mysql/sources/5.6.26/share/charsets/, ela provavelmente será diferente no seu ambiente.
Nós vamos achar um arquivo chamado Index.xml dentro desta pasta, e vamos trabalhar nele.

Neste arquivo, vamos estar utilizando a sintaxe chamada de locate data markup language (LDML), mais especificamente os elementos reset / p / t.
Você pode achar mais informação sobre a implementação de LDML no mysql neste link.

Vamos editar o arquivo e adicionar nossa collation:

<charset name="utf8">
  <family>Unicode</family>
  <description>UTF-8 Unicode</description>
  <alias>utf-8</alias>
 . . .
  <collation name="utf8_test_ci" id="1122" version="5.2.0">
    <rules>
      <reset>A</reset>
      <p>\u00c1</p>
      <t>\u00e1</t>
      <reset>E</reset>
      <p>\u00c9</p>
      <t>\u00e9</t>
      <reset>I</reset>
      <p>\u00cd</p>
      <t>\u00ed</t>
      <reset>O</reset>
      <p>\u00d3</p>
      <t>\u00f3</t>
      <reset>U</reset>
      <p>\u00da</p>
      <t>\u00fa</t>
    </rules>
  </collation>
</charset>

Explicando um pouco o que cada linha representa:

<reset>A</reset>
<p>\u00c1</p>
<t>\u00e1</t>
  • reset – está resetando a ordem e regras da letra A (e também da letra a)
  • p – está dizendo que \u00c1 (Á) será tratada como uma letra diferente
  • t – está dizendo que \u00e1 (á) será tratada como a versão minuscula de \u00c1 (Á)

A mesma lista de regras se aplica as demais letras que temos no arquivo (E / I / O / U). Agora, tudo o que precisamos é re-iniciar o serviço do MySQL.

Vamos agora testar e verificar como isto funciona na prática, vou criar 2 tabelas, uma com a collation padrão do utf8 e outra tabela com a nossa nova collation:


mysql [localhost] {msandbox} (test) > CREATE TABLE `utf8` ( `name` varchar(50), PRIMARY KEY (`name`) ) ENGINE=InnoDB DEFAULT CHARSET utf8;
Query OK, 0 rows affected (0.04 sec)

mysql [localhost] {msandbox} (test) > INSERT INTO utf8 VALUES ('A');
Query OK, 1 row affected (0.01 sec)

mysql [localhost] {msandbox} (test) > INSERT INTO utf8 VALUES ('Á');
ERROR 1062 (23000): Duplicate entry 'Á' for key 'PRIMARY'
mysql [localhost] {msandbox} (test) > INSERT INTO utf8 VALUES ('a');
ERROR 1062 (23000): Duplicate entry 'a' for key 'PRIMARY'
mysql [localhost] {msandbox} (test) > INSERT INTO utf8 VALUES ('á');
ERROR 1062 (23000): Duplicate entry 'á' for key 'PRIMARY'
mysql [localhost] {msandbox} (test) > SELECT * FROM utf8;
+------+
| name |
+------+
| A |
+------+
1 row in set (0.00 sec)

O MySQL só aceitou uma variação da letra A, todas as próximas falharam por serem consideradas iguais. Vamos ver como funciona na nossa collation:


mysql [localhost] {msandbox} (test) > CREATE TABLE `utf8_test` ( `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_test_ci , PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET utf8;
Query OK, 0 rows affected (0.03 sec)

mysql [localhost] {msandbox} (test) > INSERT INTO utf8_test VALUES ('A');
Query OK, 1 row affected (0.01 sec)

mysql [localhost] {msandbox} (test) > INSERT INTO utf8_test VALUES ('Á');
Query OK, 1 row affected (0.01 sec)

mysql [localhost] {msandbox} (test) > INSERT INTO utf8_test VALUES ('a');
ERROR 1062 (23000): Duplicate entry 'a' for key 'PRIMARY'
mysql [localhost] {msandbox} (test) > INSERT INTO utf8_test VALUES ('á');
ERROR 1062 (23000): Duplicate entry 'á' for key 'PRIMARY'
mysql [localhost] {msandbox} (test) > SELECT * FROM utf8_test;
+------+
| name |
+------+
| A |
| Á |
+------+
2 rows in set (0.00 sec)

Neste caso, o MySQL aceitou 2 variações, A / Á. “a” foi bloqueada pois é idêntica a letra “A” e “á” foi bloqueada pois é idêntica a letra “Á”.

Por hoje é isso, espero que tenham gostado.

Gostou ? Ajude e Compartilhe!
Esta entrada foi publicada em Charset, Collation, MySQL. Adicione o link permanente aos seus favoritos.