MeuMySQL Blog is now at http://blog.mdnsolutions.com/.

Tuesday, November 1, 2011

Identificadores no MySQL

Olá Pessoal. Vamos falar nesse artigo sobre Identificadores no MySQL, algo extremanente importante em nosso cotidiano com o banco de dados, mas que por vezes não entendemos bem o funcionamento.

Quando escrevemos requisições SQL,  usamos nomes para se referir a banco de dados e outros objetos contidos no mesmo, tais como tabelas, stored routines, triggers entre outros. Alguns destes objetos tem em seus componentes nomes próprios. Por exemplo, tabelas em suas colunas e índices. Ou ainda é possível criar 'apelidos' (Alias), pelo quais atuam como sinônimos para nomes de tabelas e colunas.

Sintaxe

Identificadores podem estar ou não entre acentos grave (`). Se não estiver deve seguir algumas regras:

  • Ele pode conter qualquer caracter alfanumerico, o (_) e o sinal de dolar $;
  • O identificador pode iniciar com qualquer caracter citado acima, inclusive números. Contudo, é melhor evitar identificadores que podem ser entendidos como constantes. Por exemplo 1e3 pode ser considerado um numero de notação cientifica ou 0x1 como uma contante hexadecimal. Portanto nenhum dos dois são bons candidatos à identificadores.
  • Um indentificador não pode ser apenas números.
Um identificador estando entre acentos agudos pode conter espaços, aspas simples ou duplas. Caso o SQL mode esteja habilitado em ANSI_QUOTES você também pode usar as aspas duplas ("). Usando desta forma há algumas regras para serem seguidas:
  • Em geral, qualquer caracter pode ser usado em um identificador entre aspas. Excessões neste caso são que um identificador não pode conter um byte com um valor numero 0 ou 255, e os nomes de banco de dados e tabelas não podem conter '.', '/' ou '\'.
  • Um identificador entre aspas pode conter apenas números.
  • Um identificador pode incluir qualquer palavra, mas caso esta seja uma palavra reservada (tais como SELECT ou DESC), conter caractes especiais, ou ser apenas números ele deve ser obrigatoriamente adicionado entre aspas ou acento grave.
Caso você não esteja certo se o seu identificador é ou não uma palavra reservada coloque ele entre acentos grave.


Case Sensitivity de Identificadores

Uma caracteristica que afeta como usamos identificadores é se eles são case sensitive. Alguns podem ser e outros não. As regras que determinam essas caracteristicas dependem que tipo de identificador estamos lidando:
  • Para banco de dados e tabelas o case sensitivity dependem do sistema operacional e do sistem de arquivos do servidor. Ou ainda da variável de sistema lower_case_table_names. Bancos de dados ou tabelas são representados por diretorios e arquivos, então se o sistema operacional não é case sensitive os identificadores também não são.
    O Windows não é case sensitive, porém a maioria dos sistemas Unix são. Contudo, se a a variável de sistema lower_case_table_names estiver setada para 1 ou 2, identificadores de banco de dados e tabelas são usados no estilo case-insensitive em declarações SQL. Caso deseje usar esssa variavel, você deve seta-la antes de começar a criar seus bancos de dados e tabelas.
    Independente das propriedades do seu sistema de arquivos, identificadores de bancos de dados e tabelas devem ser escritos de forma consistente com o mesmo padrão em toda declaração SQL.
  • Identificadores para colunas, índices, stored routines e triggers não sao case sensitive.
  • 'Alias' para colunas não sao case sensitive.

Utilizando 'Nomes Qualificados'

Identificadores de colunas e tabelas podem ser escritas de forma qualificada - isto quer dizer, junto com o identificador de um nivel superior utilizando o ponto '.' como separador. Algumas vezes estes qualificadores são necessários para resolver problemas de ambiguidade. Outras vezes você pode eleger seu uso para tornar uma declaração mais simples ou precisa.

Uma tabela pode ser qualificada com o nome do banco de dados que ela pertence. Ambos os casos trazem o mesmo resultado:

SELECT * FROM tb1;
SELECT * FROM db1.tb1;

Uma coluna também pode ser qualificada com o nome da tabela à que pertence. E como a tabela também pode ser qualificada podemos ter até 3 formas diferentes de escrever a mesma query:

SELECT coluna1 FROM tb1;
SELECT tb1.coluna1 FROM tb1;
SELECT db1.tb1.coluna1 FROM db1.tb1;

Store routines e triggers também podem  ser referenciados em uma forma qualificada. No primeiro caso a qualificação é pelo banco de dados à que pertence. Um trigger é associado com uma tabela, neste caso ele deve ser associado com a mesma (table_trigger.trigger_name).

Em identificadores entre aspas em nomes qualificados use eles separados. Por exemplo: db1.tb1 como `db1`.`tb1` e não `db1.tb1`.


Usando Palavras Reservadas como Identificadores

Palavras reservadas (Reserved Words) são especiais. Por exemplo, nome de funções não podem ser usadas como identificadores de tabelas ou colunas, e caso tente mensagens de erros podem ser emitidas. A declaração abaixo é um exemplo claro do uso errôneo:

mysql> CREATE TABLE t (order INT NOT NULL UNIQUE, d DATE NOT NULL);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'order INT NOT NULL UNIQUE, d DATE NOT NULL)' at line 1

Igualmente, a outra query abaixo retornará a mesma situação:

mysql> SELECT 1 AS INTEGER;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INTEGER' at line 1

A solução para estes problemas é colocar os identificadores entre aspas / acentos agudos. As regras desse encapsulamento do identificador dependem do seu tipo:
  •  Para utilizar uma palavra reservada como banco de dados, tabela, coluna ou indentificar um índice há um ou dois estilos para o encapsulamento, dependendo do SQL mode do servidor. Por padrão, palavras reservadas utilizando acento grave "`" podem ser usadas como identificadores:
mysql> CREATE TABLE t (`order` INT NOT NULL UNIQUE, d DATE NOT NULL);
Query OK, 0 rows affected (0.00 sec)

Se o ANSI_QUOTES no SQL mode estiver habilitado você pode escrever a declaração da usando aspas duplas:

mysql> CREATE TABLE t ("order" INT NOT NULL UNIQUE, d DATE NOT NULL);

Query OK, 0 rows affected (0.00 sec)
Se é necessário encapsular um identificador para sua criação, em todas as declarações envolvendo ele também será necessário executar o mesmo procedimento.
  • Pode-se usar uma palavra reservada como um 'Alias' usando aspas simples, duplas ou acento agudo. O SQL mode não faz diferença, uma vez que é legal utilizar qualquer uma das três formas. Portanto, para usar INTEGER como um 'alias' você pode escrever em todos os modos abaixo:

SELECT 1 AS 'INTEGER';SELECT 1 AS `INTEGER`;SELECT 1 AS "INTEGER";
É uma boa ideia evitar nomes de funções como identificadores. Normalmente, eles não são reservados, contudo há circunstancias pelo qual isto pode não ser verdade:
  • Algumas funções tem nomes que também são palavras chaves 'keywords' e portanto reservadas. CHAR() é um exemplo.
  • Por padrão, um nome de função seguido de um parenteses aberto deve ser escrito sem espaços entre eles. Isso permite ao statement parser do MySQL distinguir um nome em uma função do mesmo para outro propósito, tal como um identificador.
Contudo, se o IGNORE_SPACE SQL mode estiver habilitado, o servidor permite espaços entre o nome da função e seu parenteses de abertura "(". Rodando o servidor desse modo o nome de algumas funções passam a ser ambinguas em alguns contextos, uma vez que o statement parser não consegue mais distinguir seguramente se um nome representa uma função ou um identificador.
veja abaixo:

mysql> INSERT INTO COUNT (id) VALUES(43);

EM IGNORE_SPACE mode, esta declaração pode significar "criar uma nova linha na tabela COUNT, setando a coluna id com 43", ou pode significar uma falha de sintaxe na declaração INSERT que tem uma chamada da função COUNT onde o nome da tabela deveria estar. O parse não consegue distinguir.

Outra observação, palavras reservadas não são case sensitive. Elas pode ser escritas em maíusculo, minusculo ou ainda com ambos. Elas também não precisam ser escritas da mesma forma por toda a query. O mesmo também é verdadeiro para nome de funções.


No comments:

Post a Comment