Esta seção descreve como o MySQL se relaciona aos padrões ANSI/ISO SQL. O Servidor MySQL tem muitas extensões aos padrões SQL, e aqui você descobrirá quais são elas, e como usá-las. Você irá também encontrar informação sobre falta de funcionalidade do Servidor MySQL, e como trabalhar com algumas diferenças.
Nosso objetivo é não restringir, sem um boa razão, a usabilidade do MySQL Server para qualquer uso. Mesmo se não tivermos os recursos para fazer o desenvolvimento para todos os usos possíveis, estamos sempre querendo ajudar e oferecer sugestões para pessoas que estão tentando usar o MySQL Server em novos territórios.
Um dos nossos principais objetivos com o produto é continuar a
trabalhar em acordo com o padrão SQL-99, mas sem sacrificar
velocidade e confiança. Não estamos receosos em adicionar
extensões ao SQL ou suporte para recursos não SQL se ele
aumentar extremamente a usabilidade do MySQL Server para uma
grande parte de nossos utilizadores. (A nova interface
HANDLER no MySQL Server 4.0 é um exeemplo
desta estratégia. See Secção 6.4.9, “Sintaxe HANDLER”.)
Continuaremos a suportar bancos de dados transacionais e não transacionais para satisfazer tanto o uso pesado na web quanto o uso de missão crítica 24/7.
O MySQL Server foi projetado inicialmente para trabalhar com bancos de dados de tamanho médio (10-100 milhões de registros ou cerca de 100 MB por tabela) em sistemas computacionais pequenos. Continuaremos a extender o MySQL Server para funcionar ainda melhor com banco de dados na ordem de terabytes, assim como tornar possível compilar uma versão reduzida do MySQL mais apropriadas para handhels e uso embutido. O design compacto do servidor MySQL tornam ambas as direções possíveis sem qualquer conflito na árvore fonte.
Atualmente não estamos buscando suporte em tempo real (mesmo se você já puder fazer muitas coisas com nossos serviços de replicação).
Suporte a banco de dados em cluster está planejado para 2004 pela implementação de um novo mecanismo de armazenamento.
Estamos buscando melhoras no fornecimento de suporte a XML no servidor de banco de dados.
Entry-level SQL-92. ODBC levels 0-3.51.
We are aiming toward supporting the full SQL-99 standard, but without concessions to speed and quality of the code.
Se você inicializa o mysqld com a opção
--ansi ou --sql-mode=ANSI, o
seguinte comportamento é alterado no MySQL:
||é um oprador de concatenação de strings em vez de um sinônimo paraOR.‘
"’ é tratado como um caracter identificados (com o caracter de aspasr ‘`’ do MySQL Server)e não um caracter de string. Você ainda pode usar ‘`’ para citar identificadores no modo ANSI. Uma implicação disto é que você não pode usar aspas duplas para citar um string literal, porque ela será intepretada como um identificador.Você pode ter qualquer número de espaços entre um nome de função e o ‘
(’. Isto faz com que todos nomes de funções sejam tratadas como palavras reservadas. Como resultado, se você quiser acessar qualquer banco de dados, tabelas ou coluna que é uma palavra reservada, você deve colocá-lo entre aspas. Por exemplo, por haver a funçãoUSER(), o nome da tabelauserno banco de dadosmysqle a colunaUsernesta tabela se torna reservada, assim você deve colocá-la entre aspas:SELECT "User" FROM mysql."user";
REALé um sinônimo paraFLOATno lugar de um sinônimo deDOUBLE.O nível de isolamento padrão de um transação é
SERIALIZABLE. See Secção 6.7.6, “SintaxeSET TRANSACTION”.Você pode usar um campo/expressão em
GROUP BYque não está na lista de campos.
Executando o servidor em modo ANSI é o mesmo que iniciá-lo com estas opções:
--sql-mode=REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES, IGNORE_SPACE,ONLY_FULL_GROUP_BY --transaction-isolation=serializable
No MySQL 4.1, você pode conseguir o mesmo efeito com estas duas instruções:
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE; SET GLOBAL sql_mode= "REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY";
No MySQL 4.1.1 a última opção sql_mode
também pode ser dada com:
SET GLOBAL sql_mode="ansi";
No caso acima o sql_mode estará configurado
com todas as opções que são relevantes para o modo ANSI.
Você pode verificar o resultado fazendo:
mysql>SET GLOBAL sql_mode="ansi";mysql>SELECT @@GLOBAL.sql_mode;-> "REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI"
O MySQL fornece algumas extensões que você provavelmente não
irá encontrar em alguns bancos de dados SQL. Fique avisado que
se você usá-las, seu código pode não ser mais portável para
outros servidores SQL. Em alguns casos, você pode escrever
código que inclui extensões MySQL, mas continua portável,
usando comentários da forma /*! ...*/. Neste
caso, o MySQL irá analisar e executar o código com o
comentário como irá fazer com qualquer outra instrução
MySQL, mas outros servidores SQL irão ignorar as extensões.
Por exemplo:
SELECT /*! STRAIGHT_JOIN */ nome_campo FROM table1,table2 WHERE ...
Se você adicionar um número de versão depois do
'!', a sintaxe só será executada se a
versão do MySQL é igual ou maior que o número de versão
usado:
CREATE /*!32302 TEMPORARY */ TABLE t (a INT);
O exemplo acima significa que se você tiver uma versão do
MySQL 3.23.02 ou mais nova, então o MySQL irá usar a
palavra-chave TEMPORARY
Extensões MySQL são listadas abaixo:
Os tipos de campo
MEDIUMINT,SET,ENUMe os diferentes tiposBLOBeTEXT.Os atributos de campos
AUTO_INCREMENT,BINARY,NULL,UNSIGNEDeZEROFILL.Todas comparações de strings por padrão são caso insensitivo, com classificação ordenada determinada pelo conjunto de caracteres corrente (ISO-8859-1 Latin1 por padrão). Se você não gosta disso você deverá declarar suas colunas com o atributo
BINARYou usar o operadorBINARY, que fazendo com que as comparações sejam feitas de acordo com a ordem ASCII usada na máquina servidora do MySQL.O MySQL mapeia cada banco de dados em um diretório sob o diretório de dados do MySQL, e tabelas internamente num banco de dados para arquivos no diretório do banco de dados.
Isto tem algumas implicações:
Nomes de bancos de dados e tabelas são caso sensitivoo no MySQL em sistemas operacionais que possuem o sistema de arquivos caso sensitivoo (como na maioria dos sistemas Unix). See Secção 6.1.3, “Caso Sensitivo nos Nomes”.
Nomes de Bancos de dados, tabelas, índices, campos ou apelidos pode começar com um dígito (porém não podem consistir somente de digitos).
Você pode usar comandos padrão do sistemas para fazer backups, renomear, apagar e copiar tabelas. Por exemplo, para renomear uma tabela, renomeie os arquivos
.MYD,.MYIe.frm. para o nome da tabela correspondente.
Em algumas instruções SQL, você pode acessar tabelas de diferentes bancos de dados com a sintaxe
nome_bd.nome_tbl. Alguns servidores SQL fornecem a mesma funcionalidade mas chamam isto deUser space. O MySQL não suporta tablespaces como em:create table ralph.my_table...IN minha_tablespace.LIKEé permitido em campos numéricos.O uso de
INTO OUTFILEeSTRAIGHT_JOINem uma instruçãoSELECT. See Secção 6.4.1, “SintaxeSELECT”.A opção
SQL_SMALL_RESULTem uma instruçãoSELECT.EXPLAIN SELECTpara obter uma descrição de como as tabelas são ligadas.A utilização de nomes de índices, índices em um prefixo de um campo, e uso de
INDEXouKEYem uma instruçãoCREATE TABLE. See Secção 6.5.3, “SintaxeCREATE TABLE”.O uso de
TEMPORARYouIF NOT EXISTScomCREATE TABLE.O uso de
COUNT(DISTINCT lista)onde 'lista' é maior que um elemento.O uso de
CHANGE nome_campo,DROP nome_campo, ouDROP INDEX,IGNOREouRENAMEem uma instruçãoALTER TABLE. See Secção 6.5.4, “SintaxeALTER TABLE”.O uso de
RENAME TABLE. See Secção 6.5.5, “SintaxeRENAME TABLE”.Utilização de múltiplas cláusulas
ADD,ALTER,DROP, ouCHANGEem uma instruçãoALTER TABLE.O uso de
DROP TABLEcom as palavras-chaveIF EXISTS.Você pode remover múltiplas tabelas com uma instrução única
DROP TABLE.As cláusulas
ORDER BYeLIMITdas instruçõesUPDATEeDELETE.Sintaxe
INSERT INTO ... SET col_name = ....A cláusula
DELAYEDdas instruçõesINSERTeREPLACE.A cláusula
LOW_PRIORITYdas instruçõesINSERT,REPLACE,DELETEeUPDATE.O uso de
LOAD DATA INFILE. Em alguns casos essa sintaxe é compatível com o OracleLOAD DATA INFILE. See Secção 6.4.8, “SintaxeLOAD DATA INFILE”.As intruções
ANALYZE TABLE,CHECK TABLE,OPTIMIZE TABLE, eREPAIR TABLE.A instrução
SHOW. See Secção 4.6.8, “Sintaxe deSHOW”.Strings podem ser fechadas pelo ‘
"’ ou ‘'’, não apenas pelo ‘'’.O uso do meta-caractere de escape ‘
\’.A instrução
SET OPTION. See Secção 5.5.6, “Sintaxe deSET”.Você não precisa nomear todos os campos selecionados na parte
GROUP BY. Isto fornece melhor performance para algumas consultas específicas, mas muito comuns. See Secção 6.3.7, “Funções e Modificadores para Usar com CláusulasGROUP BY”.Pode ser especificado
ASCeDESCcom oGROUP BY.Para tornar mais fácil para utilizadores que venham de outros ambientes SQL, o MySQL suporta apelidos (aliases) para várias funções. Por exemplo, todas funções de string suportam as sintaxes ANSI SQL e ODBC.
O MySQL entende os operadores
||e&&como ou(OR) e e(AND) logicos, como na linguagem de programação C. No MySQL,||eORsão sinônimos, assim como&&eAND. Devido a esta ótima sintaxe, o MySQL não suporta o operador ANSI SQL para concatenação de strings||; em vez disso, use oCONCAT(). ComoCONCAT()aceita vários argumentos, é fácil converter o uso do operador||para MySQL.CREATE DATABASEorDROP DATABASE. See Secção 6.5.1, “SintaxeCREATE DATABASE”.O operador
%é um sinônimo paraMOD(). Isto é,N % Mé equivalente aMOD(N,M).%é suportado para programadores C e para compatibilidade com o PostgreSQL.Os operadores
=,<>,<=,<,>=,>,<<,>>,<=>,AND,ORouLIKEpodem ser utilizados em comparações de campos a esquerda doFROMnas instruçõesSELECT. Por exemplo:mysql>
SELECT col1=1 AND col2=2 FROM nome_tabela;A função
LAST_INSERT_ID(). See Secção 12.1.3.32, “mysql_insert_id()”.Os operadores extendidos
REGEXPeNOT REGEXPutilizados em expressões regulares.CONCAT()ouCHAR()com um ou mais de dois argumentos. (No MySQL, estas funções receber qualquer número de argumentos.)As funções
BIT_COUNT(),CASE,ELT(),FROM_DAYS(),FORMAT(),IF(),PASSWORD(),ENCRYPT(),MD5(),ENCODE(),DECODE(),PERIOD_ADD(),PERIOD_DIFF(),TO_DAYS()ouWEEKDAY().Uso de
TRIM()para cortar substrings. o SQL-99 só suporta remoção de caracteres únicos.As funções do
GROUP BY:STD(),BIT_OR(),BIT_AND()eBIT_XOR()eGROUP_CONCAT(). See Secção 6.3.7, “Funções e Modificadores para Usar com CláusulasGROUP BY”.Uso de
REPLACEno lugar deDELETE+INSERT. See Secção 6.4.7, “SintaxeREPLACE”.As instruções
FLUSH,RESETeDO.A possibilidade de configurar variáveis em uma instrução com
:=:SELECT @a:=SUM(total),@b=COUNT(*),@a/@b AS media FROM tabela_teste; SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
Nós tentamos fazer com que o MySQL siguisse os padrões ANSI SQL (SQL-92/SQL-99) e o ODBC SQL, mas em alguns casos, o MySQL realiza operações de forma diferente:
Para campos
VARCHAR, expaços extras são removidos quando o valor é armazenado. See Secção 1.8.6, “Erros Conhecidos e Deficiências de Projetos no MySQL”.Em alguns casos, campos
CHARsão alterados sem perguntas para o tipo de campoVARCHAR. See Secção 6.5.3.1, “Alteração de Especificações de Colunas”.Privilégios para uma tabela não são negadas automaticamente quando você apaga uma tabela. Você deve usar explicitamente um
REVOKEpara negar privilégios para uma tabela. See Secção 4.4.1, “A Sintaxe deGRANTeREVOKE”.
Para uma lista priorizada indicando quando novas extensões serão adicionadas ao MySQL você deve consultar lista TODO online do MySQL em http://www.mysql.com/doc/en/TODO.html. Esta é a última versão da lista TODO neste manual. See Secção 1.6, “MySQL e o Futuro (o TODO)”.
MySQL Version 4.1 supports subqueries and derived tables (unnamed views). See Secção 6.4.2, “Sintaxe de Subquery”.
For MySQL versions prior to 4.1, most subqueries can be successfully rewritten using joins and and other methods. See Secção 6.4.2.11, “Rewriting Subqueries for Earlier MySQL Versions”.
O MySQL ainda não suporta a extensão SQL do Sybase:
SELECT ... INTO TABLE .... MySQL suporta a
sintaxe ANSI SQL INSERT INTO ... SELECT
..., que é basicamente a mesma coisa. See
Secção 6.4.3.1, “Sintaxe INSERT ... SELECT”.
INSERT INTO tblTemp2 (fldID) SELECT tblTemp1.fldOrder_ID FROM tblTemp1 WHERE tblTemp1.fldOrder_ID > 100;
De maneira alternativa, você pode usar SELECT INTO
OUTFILE... ou CREATE TABLE ...
SELECT para resolver seu problema.
O MySQL Server (versão 3.23-max e todas as versões 4.0 e
acima) suportam transações com os mecanismos de
armazenamento transacionais
InnoDB e BDB.
InnoDB fornece compatibilidade
total com ACID. See
Capítulo 7, Tipos de Tabela do MySQL.
Os outros tipos de tabelas não transacionais (tais como
MyISAM) no MySQL Server seguem um paradigma
diferente para integridade de dados chamado
``Operções Atômicas.'' Em termos de
transação, tabelas MyISAM efetivamente
sempre operam em modo AUTOCOMMIT=1.
Operações atômicas geralmente oferecem integridade
comparável com a mais alta performance.
Com o MySQL Server suportando ambos os paradigmas, o utilizador pode decidir se precisa da velocidade das operações atômicas ou se precisa usar recursos transacionais em seu aplicativo. Esta escolha pode ser feita em uma base por tabela.
Como notado, a comparação para tabelas transacionais vs.
não transacionais As noted, the trade off for transactional
vs. non-transactional table se encontra em grande parte no
desempenho. Tabelas transacionais tem uma exigência de
memória e espaço em disco significantemente maior e maior
sobrecarga da CPU. Tipos de tabelas transacionais como
InnoDB oferecem muitos recursos únicos. O
projeto modular do MySQL Server permite o uso concorrente de
todas estes mecanismos de armazenamento para servir a
diferentes exigências e oferecer um ótimo desempenho em
todas as situações.
Mas como fazer uso dos recursos do MySQL Server para manter
uma integridade rigorosa mesmo com tabelas
MyISAM não transacionais e como este
recurso se compara com os tipos de tabelas transacionais?
No paradigma transacional, se as suas aplicações são escritas de uma forma que é dependente na chamada de
ROLLBACKem vez deCOMMITem situações críticas, então transações são mais convenientes. Além disso, transações asseguram que atualizações inacabadas ou atividades corrompidas não sejam executadas no banco de dados; o servidor oferece uma oportunidade para fazer um rollback automático e seu banco de dados é mantido.O MySQL Server, na maioria dos casos, permite a você resolver potenciais problemas incluindo simples conferências antes das atualizações e executando scripts simples que conferem inconsistências no banco de dados e, automaticamente, repara ou avisa caso isto ocorra. Perceba que apenas usando o log do MySQL ou mesmo adicionando um log extra, pode-se corrigir tabelas perfeitamente sem nenhuma perda de integridade.
Mais do que nunco, atualizações transacionais fatais podem ser reescritas para serem atômicas. De fato podemos dizer que todos problemas de integridade que transações resolvem podem ser feitas com
LOCK TABLESou atualizações atômicas, assegurando que você nunca irá ter uma finalização automática da tabela, o que é um problema comum em bancos de dados transacionais.Nem mesmo transações podem prevenir todas as falhas se o servidor cair. Nestes casos mesmo um sistema transacional pode perder dados. A diferença entre sistemas diferentes é apenas em quão pequeno é o lapso de tempo em que eles podem perder dados. Nenhum sistema é 100% seguro, somente ``seguro o suficiente.'' Mesmo o Oracle, com reputação de ser o mais seguro bancos de dados transacionais, tem relatos de algumas vezes perder dados nestas situações.
Para estar seguro com o MySQL Server, você apenas deve fazer backups e ter o log de atualizações ligado. Com isto você pode se recuperar de qualquer situação possível com bancos de dados transacionais. É sempre bom ter backups, independente de qual banco de dados você usa.
O paradigma transacional tem seus benefícios e suas desvantagens. Muitos utilizadores e desenvolvedores de aplicações dependem da facilidade com a qual eles podem codificar contornando problemas onde abortar parece ser, ou é necessário. No entanto, se você é novo no paradigma de operações atômicas ou tem mais familiaridade ou conforto com transações, considere o benefício da velocidade que as tabelas não transacionais podem oferece, na ordem de 3 a 5 vezes da velocidade que as tabelas transacionais mais rápidas e otimizadas.
Em situações onde integridade é de grande importância, as
atuais características do MySQL permitem níveis
transacionais ou melhor confiança e integridade. Se você
bloquear tabelas com LOCK TABLES todos as
atualizações irão ser adiadas até qualquer verificação
de integridade ser feita. Se você só obter um bloqueio de
leitura (oposto ao bloqueio de escrita), então leituras e
inserções poderão ocorrer. Os novos registros inseridos
não poderão ser visualizados por nenhum dos clientes que
tiverem um bloqueio de LEITURA até eles
liberarem estes bloqueios. Com INSERT
DELAYED você pode enfileirar inserções em uma
fila local, até os bloqueios serem liberados, sem que o
cliente precise esperar atá a inserção completar. See
Secção 6.4.3.2, “Sintaxe INSERT DELAYED”.
``Atômico'', no sentido em que nós mencionamos, não é mágico. Significa apenas que você pode estar certo que enquanto cada atualização específica está sendo executada, nenhum outro utilizador pode interferir com ela, e nunca haverá um rollback automático (que pode acontecer em sistemas baseados em transações se você não tiver muito cuidado). O MySQL também assegura que nunca ocorrerá uma leitura suja.
A seguir estão algumas técnicas para trabalhar com tabelas não transacionais:
Loops que precisam de transações normalmente pode ser codificados com a ajuda de
LOCK TABLES, e você não precisa de cursores para atualizar regitros imeditamente.Para evitar o uso do
ROLLBACK, você pode usar as seguintes estratégias:Use
LOCK TABLES ...para fazer um lock todas as tabelas que você quer acessar.Condições de teste.
Atualize se estiver tudo OK.
Use
UNLOCK TABLESpara liberar seus locks.
Isto é normalmente um método muito mais rápido que usar transações com possíveis
ROLLBACKs, mas nem sempre. A única situação que esta solução não pode tratar é quando alguém mata a threads no meio de uma atualização. Neste caso, todas os locks serão liberados mas algumas das atualização podem não ter sido execuadas.Você também pode usar funções para atualizar registros em uma única operação. Você pode conseguir uma aplicação muito eficiente usando as seguintes técnicas:
Modifique campos em relação ao seus valores atuais.
Atualize apenas aqueles campos que realmente tiveram alterações.
Por exemplo, quando fazemos atualizações em alguma informação de cliente, atualizamoa apenas os dados do clientes que alteraram e testamos apenas aqueles com dados alterados ou dados que dependem dos dados alterados, mudaram em comparação com o registro original. O teste dos dados alterados é feito com a cláusula
WHEREna instruçãoUPDATE. Se o registro não foi atualizado, mandamos ao cliente uma mensagem: ''Some of the data you have changed has been changed by another user.'' Então mostramos o registro antigo versus o novo em uma janela, assim o utilizador pode decidir qual versão do registro de cliente de ser usado.Isto nos dá algo similar a lock de colunas mas que, na verdade, é melhor porque apenas atualizamos algumas das colunas, usando valores relativos ao seu valor atual. Isto significa que instruções
UPDATEcomuns se parecem com estas:UPDATE nometabela SET pay_back=pay_back+125; UPDATE customer SET customer_date='current_date', address='new address', phone='new phone', money_he_owes_us=money_he_owes_us-125 WHERE customer_id=id AND address='old address' AND phone='old phone';
Como você pode ver, isto é muito eficiente e funciona mesmo se outro cliente alterar os valores nas colunas
pay_backoumoney_he_owes_us.Em muitos casos, utilizadores querem fazer
ROLLBACKe/ouLOCK TABLEScom o propósito de gerenciarem identificadores únicos para algumas tabelas. Isto pode ser tratado muito mais eficientemente usando uma colunaAUTO_INCREMENTe também uma função SQLLAST_INSERT_ID()ou a função da API Cmysql_insert_id(). See Secção 12.1.3.32, “mysql_insert_id()”.Geralmente você pode codificar evitando lock de registro. Algumas situações realmente precisam disto, e tabelas
InnoDBsuportam lock de regitstro. Comoo MyISAM, você pode usar uma coluna de flag na tabela e fazer algo como a seguir:UPDATE nome_tbl SET row_flag=1 WHERE id=ID;
O MySQL retorna 1 para o número de linhas afetadas se as linhas foram encontradas e
row_flagjá não era 1 na linha original.Você pode pensar nisto como se o MySQL Server tivesse alterado a consulta anterior para:
UPDATE nome_tbl SET row_flag=1 WHERE id=ID AND row_flag <> 1;
Steored procedures estão sendo implementadas em nossa versão 5.0 na árvore de desenvolvimento. See Secção 2.3.4, “Instalando pela árvore de fontes do desenvolvimento”.
Este esforço é baseado no SQL-99, que têm uma sintaxe básica similar (mas não idêntica) ao Oracle PL/SQL. Em adição a isto, estamoas implementando o framework SQL-99 enganchar em linguagens externas.
Uma Stored Procedure é um conjunto de comandos SQL que podem ser compilados e armazenados no servidor. Uma fez feito isso, os clientes não necessitam reescrever toda a consulta mas podem fazer referência à stored procedure. Isto fornece melhor performance porque a query necessita ser analisada pelo servidor somente uma vez, e necessita menos informação para ser enviada entre o servidor e o cliente. Você também pode elevar o nível conceitual tendo bibliotecas de funções no servidor. No entanto, stored procedures aumentam a carga no servidor de banco de dados, já que grande parte do trabalho é feito do lado do servidor e menos do lado do cliente (aplicação).
Triggers estão programados para serem implementados no MySQL versão 5.1. Um trigger é um tipo de stored procedure que é chamado quando um evento em particular ocorre. Por exemplo, você poderia configurar uma stored procedure que é disparada toda vez que um registro for apagado de uma tabela transacional que automaticamente apaga o cliente correspondente de uma tabela de clientes quando todas as transações forem removidas.
No MySQL Server 3.23.44 e posterior, tabelas
InnoDB suportam verificação de
restrição de chaves estrangeiras, incluindo
CASCADE, ON DELETE, e
ON UPDATE. See
Secção 7.5.5.2, “Restrições FOREIGN KEY”.
Para outros tipos de tabela, o MySQL Server atualmente apenas
analisa a sintaxe de FOREIGN KEY no comando
CREATE TABLE, mas não usa/armazena esta
informação. Em um futuro próximo esta implementação será
estendida para que assim a informação seja armazenada num
arquivo de especificação de tabela e possa ser recuperado
por mysqldump e ODBC. Em um estágio
posterior, restrições de chaves estrangeiras serão
implementadas para tabelas MyISAM.
Note que as chaves estrangeiras no SQL não são usadas para
ligar tabelas, mas são usadas para verificar a integridade
referencial. Se você deseja obter resultados de múltiplas
tabelas de uma instrução SELECT, você
pode fazer isto ligando tabelas:
SELECT * FROM table1,table2 WHERE table1.id = table2.id;
See Secção 6.4.1.1, “Sintaxe JOIN”. See
Secção 3.6.6, “Utilizando Chaves Estrangeiras”.
Quando usada como uma restrição, FOREIGN
KEYs não precisa ser usado se a aplicação insere
duas linhas em tabelas MyISAM na ordem
apropriada.
Para tabelas MyISAM, você pode contornar a
falta de ON DELETE adicionando a
instrução DELETE apropriada a uma
aplicação quando você deletar registros de uma tabela que
tem uma chave estrangeira. Na prática isto é mais rápido e
muito mais portável que utilizar chaves estrangeiras.
No MySQL Server 4.0 você pode utilizar deleções
multi-tabela para apagar linha de muitas tabelas com um
comando. See Secção 6.4.5, “Sintaxe DELETE”.
A sintaxe FOREIGN KEY sem ON
DELETE ... é usada geralmente por aplicacões ODBC
para produzir cláusulas WHERE
automáticas.
Note que chaves estrangeiras são mal usadas com frequência, o que pode causar graves problemas. Mesmo quando usado apropriadamente, o suporte a chaves estrangeiras não é uma solução mágica para o problema de integridade referêncial, embora possa ajudar.
Algumas vantagens das chaves estrangeiras:
Assumindo o projeto apropriado das relações, as restrições de chaves estrangeiras tornarão mais difícil para um programador introduzir uma inconsistência no banco de dados.
Usar atualizações e deleções em cascata pode simplificar o código do cliente.
Regras de chaves estrangeiras projetados apropriadamente ajudam ao documentar a relação entre as tabelas.
Desvantagens:
Erros, que são facéis de se ter ao projetar a relação das chaves, podem causar graves problemas¯por exemplo, regras circulares ou a combinação errada de uma deleção em cascata.
Verificação adicional no banco de dados afeta o desempenho, por esta razão algumas das principais aplicações comerciais codificam sua lógica no nível da aplicação.
Não é incomum para um DBA fazer uma topologia complexa de relações que torna muito difícl, e em alguns casos impossível, fazer backup ou restaurar tabelas individuais.
Views estão senda implementadas atualmente e aparecerão na versão 5.0 e 5.1 do MySQL Server.
Historicamente o MySQL Server tem sido mais usado em aplicações e sistemas web onde o desenvolvedor da aplicação tem total controle sobre o uso do banco de dados. É claro que o uso aumentou em várias vezes e então descobrimos que um crescente números de utilizadores consideram views como um importante aspecto.
Unnamed views (derived tables, uma
seubquery na cláusula FROM de uma
SELECT) já estão implementadas na versão
4.1.
Views geralmente são muito úteis para permitir aos utilizadores acessar uma série de relações (tabelas) como uma tabela, e limitar o acesso a apenas estas relações. Views também podem ser usadas para restringir o acesso aos registros (um subconjunto de uma tabela em particular). Mas views não são necessárias para restringir o acesso a registros já que o MySQL Server tem um sofisticado sistema de privilégios. See Secção 4.3, “Detalhes Gerais de Segurança e o Sistema de Privilégio de Acesso do MySQL”.
Muitos SGBD não permitem atualizar nenhum registro em uma view, mas você tem que fazer as atualizações em tabelas separadas.
Em nosso projeto de implemtação de views, nós buscamos (tanto quanto for possível dentro do SQL) compatibilidade com ``Codd's Rule #6'' para sistemas de banco de dados relacionais: todos os views que são teoricamente atualizáveis, devem se atualizados também na prática.
Outros bancos de dados SQL usam '--' para
iniciar comentários. O MySQL usa
‘#’ como o caractere para
início de comentário, mesmo se a ferramenta de linha de
comando mysql remover todas linhas que
começam com '--'. Você também pode usar o
comentário no estilo C /*isto é um
comentário*/ com o MySQL Server. See
Secção 6.1.6, “Sintaxe de Comentários”.
O MySQL Server versão 3.23.3 e superior suporta o estilo de
comentário '--' somente se o comentário for
seguido por um caractere de espaço (ou por um caracter de
controle como uma nova linha). Isto ocorre porque este estilo
de comentário causou muitos problemas com queries SQL geradas
automaticamente que usavam algo como o código seguinte, onde
automaticamente erá inserido o valor do pagamento para
!pagamento!:
UPDATE nome_tabela SET credito=credito-!pagamento!
O que você acha que irá acontecer quando o valor de
pagamento for negativo? Como
1--1 é legal no SQL, nós achamos
terrível que '--' signifique início de
comentário.
Usando a nossa implementação deste método de comentário no
MySQL Server Version 3.23.3 e posterior, 1-- Isto é
um comentário é atualmente seguro.
Outro recurso seguro é que o cliente de linha de comando
mysql remove todas as linhas que iniciam
com '--'.
A seguinte discussão somente interessa se você estiver executando uma versão do MySQL inferior a versão 3.23:
Se você tem um programa SQL em um arquivo texto que contêm
comentários '--' você deverá usar:
shell>replace " --" " #" < arquivo-texto-com-comentário.sql \| mysql banco-de-dados
No lugar de:
shell> mysql banco-de-dados < arquivo-texto-com-comentario.sql
Você também pode editar o próprio arquivo de comandos
alterando os comentários '--' para
‘#’:
shell> replace " --" " #" -- arquivo-texto-com-comentario.sql
Desfaça utilizando este comando:
shell> replace " #" " --" -- arquivo-texto-com-comentario.sql
Como o MySQL lhe permite trabalhar com tabelas transacionais e não transacionais (que não permitem rollback), o tratamento de restrições é um pouco diferente no MySQL que em outros bancos de dados.
Temos que tratar o caso quando você atualiza diversos registros com uma tabela não transacional que não pode fazer rollback em erros.
A filosofia básica é tentar obter um erro para qualquer coisa que possamos detectar em temp de compilação mas tentar recuperar de qualquer erro que abtemos em tempo de execução. Fazemos isto na maiorioa dos casos, mas não para todos ainda. See Secção 1.6.4, “Novos Recursos Planejados Para a Versão em um Futuro Próximo”.
A opção básica que o MySQL tem é parar a instrução no meio ou fazer o melhor para se recuperar do problema e continuar.
A seguir mostramos o que acontece com diferentes tipos de restrições.
Normalmente você receberá um erro quando tentar fazer um
INSERT / UPDATE de um
registro que cause uma violação de uma chave primária,
chave única ou chave estrangeira. Se você estiver usando um
mecanismo de armazenamento transacional, como InnoDB, o MySQL
automaticamente fará um rollback da transação. Se você
estiver usando mecanismos de armazenemento não transacionais
o MySQL irá para no registro errado e deiar o resto dos
registros se processamento.
Para tornar a vida mais fácil o MySQL adicionou suporte a
diretiva IGNORE para a maioria dos comandos
que podem causar uma violação de chave (como INSERT
IGNORE ...). Neste caso o MySQL irá ignorar
qualquer violação de chave e continuará com o processamento
do próximo registro. Você pode obter informação sobre o
que o MySQL fez com a função da API
mysql_info() API function e em versões
posteriores do MySQL 4.1 com o comando SHOW
WARNINGS. See Secção 12.1.3.30, “mysql_info()”. See
Secção 4.6.8.9, “SHOW WARNINGS | ERRORS”.
Note que no momento apenas as tabelas
InnoDB suportam chaves estrangeiras. See
Secção 7.5.5.2, “Restrições FOREIGN KEY”.
O suporte a chaves estrangeiras nas tabelas
MyISAM está programado para ser incluída
na arvoré de fonte do MySQL 5.0.
Para poder suportar um fácil tratamento de tabelas não transacionais todos os campos no MySQL têm valores padrão.
Se você inserir um valor 'errado' em uma coluna como um
NULL em uma coluna NOT
NULL ou um valor numérico muito grande em um campo
numérico, o MySQL irá atribuir a coluna o 'melhor valor
possível' em vez de dar uma mensagem de erro. Para strings
este valor é uma string vazia ou a maior string possível que
possa estar na coluna.
Isto significa que se você tentar armazenar
NULL em uma coluna que não aceita valores
NULL, o MySQL Server armazenará 0 ou
'' (strig vazia) nela. Este último
comportamento pode, para uma simples inserção de registro,
ser alterado com a opção de compilação
-DDONT_USE_DEFAULT_FIELDS.) See
Secção 2.3.3, “Opções típicas do configure”. Isto faz com que as
instruções INSERT gerem um erro a menos
que você explicite valores específicos para todas as colunas
que exigem um valor diferente de NULL.
A razão para as regras acima é que não podemos verificar estas condições antes da consulta começar a executar. Se encontrarmos um problema depois de atualizar algumas linahs, não podemos fazer um rollback já que o tipo de tabela não suporta isto. A opção de parar não é tão boa como no caso em que a atualização esteja feita pela metade que é provavelmente o pior cenário possível. Neste caso é melhor 'fazer o possível' e então continuar como se nada tivesse acontecido. No MySQL 5.0 plenejamos melhorar into forncendo avisos para conversões automáticas de campo, mais uma opção para deixar você fazer um rollback das instruções que usam apenas tabelas transacionais no caso de tal instrução fizer uma definição de campo não permitida.
O mostrado acima significa que não se deve usar o MySQL para verificar o conteúdo dos campos, mas deve se fazê-lo por meio da aplicação.
No MySQL 4.x ENUM não é uma restrição
real, mas um modo mauis eficiente de armazenar campos que
possam apenas conter um conjunto de valores dados. Isto é
devido as mesmas razões pelas quais NOT
NULL não é respeitado. See
Secção 1.8.5.2, “Restrições de NOT NULL”.
Se você inserir um valor errado em um campo
ENUM, ele será configurado com uma string
vazia em um contexto string. See Secção 6.2.3.3, “O Tipo ENUM”.
Se você inserir uma opção errada em um campo
SET, o valor errado será ignorado. See
Secção 6.2.3.4, “O Tipo SET”.
Os seguintes erros/bugs conhecidos não estão corrigidos no MySQL 3.23 porque corrigí-los involveria a mudança de muito código, o que poderia introduzir outros erros, talvez piores. Os erros são também classificados como 'não fatal' ou 'tolerável'.
Pode se obter um deadlock ao fazer
LOCK TABLEem multiplas tabelas e então na mesma conexão fizer umDROP TABLEem uma delas enquanto outra thread está tentando bloquear a tabela. Pode-se no entanto fazer umKILLem qualquer uma das threads envolvidas para resolver isto. Corrigido na versão 4.0.12SELECT MAX(campo_chave) FROM t1,t2,t3...onde uma das três tabelas está vazia não retornaNULL, mas sim o valor máximo da coluna. Corrigido na versão 4.0.11.DELETE FROM heap_tablesem umWHEREnão funcionam em tabelas HEAP com lock.
Os seguintes problemas são conhecidos e tem prioridade muito alta para serem corrigidos:
FLUSH TABLES WITH READ LOCKnão bloqueiaCREATE TABLEouCOMMIT, que pode criar um problema com a posição do log binário ao se fazer um backup completo de tabelas e do log binário.ANALYZE TABLEem uma tabela BDB pode, em alguns, casos inutilizar a tabela até que se reinicie o servidormysqld. Quando isto acontecer você irá ver o seguinte tipo de erro no arquivo de erros do MySQL.001207 22:07:56 bdb: log_flush: LSN past current end-of-log
O MySQL aceita parenteses na parte
FROM, mas os ignora sem aviso. A razão pela qual não são retornados erros é que muitos clientes que geram consultas automaticamente adicionam parentesis na parteFROMmesmo onde eles não são necessários.Concatenar muitos
RIGHT JOINSou combinar joinsLEFTeRIGHTna mesma consulta podem dar uma resposta incorreta ja que o MySQL só gera registrosNULLpara tabelas que precedem um joinLEFTou antes de um joinRIGHT. Isto será corrigido na versão 5.0 junto com o suporte a parentesis na parteFROM.Não execute
ALTER TABLEem uma tabelaBDBem que você estiver executando transações multi-instruções não completadas. (A transação provavelmente será ignorada).ANALYZE TABLE,OPTIMIZE TABLEeREPAIR TABLEpodem causar problemas em tabelas para as quais você estiver usandoINSERT DELAYED.Fazendo um
LOCK TABLE ..eFLUSH TABLES ..não garante que não existem transações não terminadas em progresso na tabela.Tabelas BDB são um pouco lentas para abrir. Se você tiver várias tabelas BDB em um banco de dados, gastará muito tempo para usar o cliente
mysqlno banco de dados se você não estiver usando a opção-Aou se você estiver usandorehash. Isto é percebido principalmente quando você tiver um cache de tabelas grandes.A replicação utiliza o log a nivel de consulta: o master grava a consulta no log binário. Isto é um rápido, compacto e eficiente método de registro o que funciona perfeitamente na maioria dos casos. Embora nunca tenhamos ouvido sobre um caso ocorrido, há uma chance teórica que o dado no master e slave sejam diferente se uma consulta é feita de tal modo que a modificação do dado é não determinística, isto é, deixar ao desejo do otimizador de consultas (o que geralmente não é uma boa prática, mesmo fora da replicação!). Por exemplo:
CREATE ... SELECTouINSERT ... SELECTque preenchem com zeros ouNULLuma colunaauto_increment.DELETEse você estiver apagando registros de uma tabela que tem chaves estrangeiras com a propriedadeON DELETE CASCADE.REPLACE ... SELECT,INSERT IGNORE ... SELECTse você tiver valores de chaves duplicados nos dados inseridos.
Se e somente se todos estas consultas NÃO tiverem cláusulas
ORDER BYgarantindo uma ordem determinística.Na verdade, por exemplo para
INSERT ... SELECTsemORDER BY, oSELECTpode retornar registros em uma ordem diferente (no qual resultará em um registro tendo diferentes posições, obtendo um número diferente na colunaauto_increment), dependendo da escolhe feita pelo otimizador no master e slave. Uma consulta será otimizada deiferentemente no master e slave apenas se:Os arquivos usados pelas duas consultas não são exatamente a mesma; por exemplo
OPTIMIZE TABLEfoi executado nas tabelas master e não nas nas tabelas slave (para corrigir isto, desde o MySQL 4.1.1,OPTIMIZE,ANALYZEeREPAIRsão escritos no log binário).A tabela está armazenada em um mecanismo de armazenamento diferente no master e no slave (pode se executar diferentes mecanismos de armazenamento no metre e no slave: por exemplo, InnoDB ne master e MyISAM no slave, se o slave possuir menos espaço dispponível em disco).
The MySQL buffers' sizes (
key_buffer_sizeetc) are different on the master and slave.O master e slave executam versões diferentes do MySQL, e o código do toimizador é diferente entre estas versões.
Este problema também pode afetar a restauração de um banco de dados usando
mysqlbinlog|mysql.O modo mais fácil de evitar este problema em todos os casos é adicionar uma cláusula
ORDER BYpara tal consulta não determinística assegure que os registros são sempre armazenados/modificados na mesma ordem. Nas versões futuras do MySQL adicionaremos automaticamente uma cláusulaORDER BYquando necessário.
Os seguintes problemas são conhecidos e serão corrigidos na hora certa:
Ao usar funções
RPAD, ou qualquer outra função string que termina adicionando espaços em branco a direita, em uma consulta que preisa usar tabelas temporárias para ser rsolvida, todas as strings resultantes serão cortadas a direita (como em RTRIM). Este é um exemplo de uma consulta:SELECT RPAD(t1.field1, 50, ' ') AS f2, RPAD(t2.field2, 50, ' ') AS f1 FROM table1 as t1 LEFT JOIN table2 AS t2 ON t1.record=t2.joinID ORDER BY t2.record;O resultado final deste erro é que o utilizador não conseguira espaços em branco do lado direito do campo resultante.
O comportamento anterior existe em todas as versões do MySQL.
A razão disto é devido ao fato de tabelas HEAP, que são usadas primeiro para tabelas temporárias, não são capazes de tratar colunas VARCHAR.
Este comportamento será corrigido em uma das distribuições da série 4.1.
Devido ao modo como os arquvos de definições de tabelas são armazenados não se pode usar 255 caracteres (
CHAR(255)) em nomes de tabelas, nomes de colunas e enum. Isto está programado para ser corrigido na versão 5.1 quando temos novos arquivos de formatos de definição de tabelas.Quando estiver usando
SET CHARACTER SET, não é permitido usar caracteres especias no nome do banco de dados, tabelas ou campos.Pode-se usar
_ou%comESCAPEemLIKE ... ESCAPE.se você tiver uma coluna
DECIMALcom um número armazenado em diferentes formatos (+01.00, 1.00, 01.00),GROUP BYpode considerar cada valor como um valor diferente.DELETE FROM merge_tableusado semWHEREirá apenas apagar o mapeamento para a tabela, não apagando tudo nas tabelas mapeadas.Você não pode construir em outro diretório quando estiver utilizando MIT-pthreads. Como isto necessitaria de alterações na MIT-pthreads, nós não estamos aptos a corrigí-la.
BLOBvalores não podem ser usados com confiança emGROUP BY,ORDER BYouDISTINCT. Somente os primeiros bytes (padrão 1024)max_sort_lengthsão usados quando estiver comparandoBLOBs nestes casos. Isto pode ser alterado com a opção-0 max_sort_lenghtparamysqld. Uma forma de contornar este problema para a maioria dos casos é usar a substring:SELECT DISTINCT LEFT(blob,2048) FROM nome_tabela.Cálculos são feitos com
BIGINTouDOUBLE(normalmente, ambos tem o tamanho de 64 bits). Depende da precisão utilizada na função. A regra geral é que funções binárias são feitas com precisãoBIGINT,IFeELT()com precisãoBIGINTouDOUBLEe o resto com precisãoDOUBLE. Devemos evitar o uso de valores sem sinal maiores que 63 bits (9223372036854775807) para qualquer outra coisa além de campos binários!Todas os campos string, exceto campos do tipo
BLOBeTEXTOtem, automaticamente, todos os espaços extras removidos quando recuperados. Para tiposCHAR, isto não tem problema, e pode ser considerado como um recurso de acordo com o ANSI SQL92. O problema é que no MySQL, camposVARCHARsão tratados desta mesma forma.Você só pode ter até 255 colunas
ENUMeSETem uma tabela.Em
MIN(),MAX()e outras funções de agrupamente, o MySQL atualmente compara as colunasENUMeSETpelo valor de suas strings ao invés da posição relativa da string no conjunto.mysqld_saferedireciona todas as mensagens demysqldpara o logmysqld. Um problema com isto é que se você executar omysqladmin refreshpara fechar e reabrir o log, astdoute astderrcontinuam redirecionadas para o log antigo. Se você utiliza--logextensivamente, deverá editar omysqld_safepara logar em'hostname'.errem vez de'hostname'.log; assim você pode facilmente utilizar o espaço do log antigo apagando-o e executandomysqladmin refresh.Em instruções
UPDATE, colunas são atualizadas da esquerda para a direita. Se você referenciar a uma coluna atualizada, você irá obter o valor atualizado em vez do valor original, por exemplo:mysql>
UPDATE nome_tabela SET KEY=KEY+1,KEY=KEY+1;Isto atualiza
KEYcom2no lugar de1.Você pode se referir a múltiplas tabelas em uma mesma consulta, mas você não pode se referir a qualquer tabelas temporárias dada mais de uma vez. Por exemplo, a seguinte instrução não funciona.
mysql>
SELECT * FROM temporary_table, temporary_table AS t2;RENAMEnão funciona com tabelas temporárias (TEMPORARY) ou tabelas usadas em uma tabelasMERGE.O otimizador pode lidar com o
DISTINCTde forma diferente se você estiver usando colunas 'escondidas' em uma join ou não. Em uma join, colunas escondidas são contadas como parte do resultado (mesmo se elas não são mostradas) enquanto que em queries normais colunas escondidas não participam na comparaçãoDISTINCT. Nós provavelmente iremos alterar isto no futuro para nunca comparar as colunas escondidas quando executandoDISTINCT.um exemplo disto é:
SELECT DISTINCT mp3id FROM band_downloads WHERE userid = 9 ORDER BY id DESC;
and
SELECT DISTINCT band_downloads.mp3id FROM band_downloads,band_mp3 WHERE band_downloads.userid = 9 AND band_mp3.id = band_downloads.mp3id ORDER BY band_downloads.id DESC;
No segundo caso, você pode obter duas linhas idênticas no MySQL 3.23.x na série do resultado (porque o campo escondido 'id' pode variar).
Perceba que isto somente acontece em consultas onde você não tem colunas ORDER BY no resultado, algo não permitido no SQL-92.
Como o MySQL permite trabalhar com tipos de tabelas que não suportam transações (e assim não pode fazer
rollbackem dados) algumas coisas funcionam um pouco diferentes de outros servidores SQL em MySQL (Isto serve para garantir que o MySQL nunca necessitará de um rollback para um comando SQL). Porém isto pode ser um pouco estranho em casos que os valores dos campos devem ser verificados na aplicação, mas isto ira fornacer um ótimo ganho de velocidade assim como permite ao MySQL fazer algumas otimizações que de outro modo seriam muito difíceis para serem feitas.Se você informar um valor incorreto em uma coluna, o MySQL, em vez de fazer um rollback, aramzenará o
melhor valor possívelno campo.Se tentar armazenar um valor fora da faixa em uma coluna numérico, o MySQL irá armazenar o menor ou maior valor possível no campo.
Se tentar armazenar uma string que não comece com um número em uma coluna numérica, o MySQL irá armazenar 0 na coluna.
Se você tentar armazenar
NULLem uma coluna que não aceita valores nulos, MySQL irá armazenar 0 ou''(string vazia) na coluna. (Este comportamento pode, entretanto, ser alterado com a opção de compilação -DDONT_USE_DEFAULT_FIELDS).O MySQL permite o armazenamento de alguns valores errados de data em campos do tipo
DATEeDATETIME. (Como 2000-02-31 ou 2000-02-00). A idéia é que não é serviço do servidor SQL validar datas. Se o MySQL pode armazenar uma data e recuperar extamente a mesma data, então o MySQL armazenará a data. Se a data estiver totalmente errada, o MySQL irá armazenar a data 0000-00-00 no campo.Se você especificar um valor não suportado para um campo do tipo
enum, ele será alterado para o valor de erro 'empty string', com valor numérico 0.Se você definir uma coluna
SETcom um valor não suportado, o valor será ignorado.
Se você executar uma
PROCEDUREem uma pesquisa que retorna uma série vazia, em alguns casos a instruçãoPROCEDUREnão irá transformar as colunas.Criação da tabela do tipo
MERGEnão verifiva se as tabelas envolvidas são de tipos compatíveis.O MySQL ainda não pode lidar com valores
NaN,-InfeInfem tipos double. Usá-los causará problemas na exportação e importação de dados. Uma solução intermediária é alterarNaNparaNULL(se for possível) e-InfeInfpara o valordoublemínimo ou máximo respectivo possível.Se você usar
ALTER TABLEpara primeiro adicionar um índiceUNIQUEa uma tabela usada em uma tabelaMERGEe então usarALTER TABLEpara adicionar um índice normal na tabelaMERGE, a ordem das chaves será diferente para as tabelas se existir uma chave antiga não única na tabela. Isto é porque oALTER TABLEcoloca chavesUNIQUEantes de chaves normais para ser possível detectar chaves duplicadas o mais cedo o possível.
Os seguintes erros são conhecidos em versões mais antigas do MySQL:
Você pode pendurar um processo se você fizer um
DROP TABLEem uma tabela entre outras que esteja travada comLOCK TABLES.No caso seguinte você pode obter um descarrego de memória para o arquivo core:
Tratamento de inserções com atraso tem deixado inserções pendentes na tabela.
LOCK tablecomWRITEFLUSH TABLES
Antes da versão 3.23.2 do MySQL um
UPDATEque atualizava uma chave com umWHEREna mesma chave podia falhar porque a chave era usada para procurar por registros e a mesma linha poderia ter encontrado vários itens:UPDATE nome_tabela SET KEY=KEY+1 WHERE KEY > 100;
Um modo de contornar este erro é utilizar:
mysql>
UPDATE nome_tabela SET KEY=KEY+1 WHERE KEY+0 > 100;Isto funcionará porque MySQL não utilizará indices em expressões com a cláusula
WHERE.Antes da versão 3.23 do MySQL, todos os tipos numéricos tratados como campos de pontos fixos. Isto significa que você tem que especificar quantas casas decimais um campo de ponto flutuante deve ter. Todos os resultados eram retornados com o número correto de casas decimais.
Para erros específicos na plataforma, vejas as seções sobre compilação e portabilidade. See Secção 2.3, “Instalando uma distribuição com fontes do MySQL”. See Apêndice E, Portando para Outros Sistemas.

