Por que uma coluna de texto não pode ter um valor padrão no MySQL?

185

Se você tentar criar uma coluna TEXT em uma tabela e atribuir a ela um valor padrão no MySQL, você receberá um erro (pelo menos no Windows). Não vejo nenhum motivo para uma coluna de texto não ter um valor padrão. Nenhuma explicação é dada na documentação do MySQL. Parece ilógico para mim (e um tanto frustrante, pois quero um valor padrão!). Alguém sabe por que isso não é permitido?

Russ
fonte
1
Podemos ver a consulta que você usou?
Robert
2
Tem certeza de que deseja uma coluna TEXT, não uma coluna VARCHAR? As colunas TEXT são para itens que podem ter mais de 255 bytes.
scy
5
Isso deve ser um comentário. Além disso, sim, ele quer dizer TEXT- essas colunas não podem ter um valor padrão. VARCHARpode.
Pekka
1
Se você estiver usando o phpmyadmin para configurar seu banco de dados, talvez queira investigar o mysql gui tools / workbench ...;)
dmp
1
Sim, infelizmente preciso de mais de 255 caracteres.
Russ

Respostas:

92

O Windows MySQL v5 gera um erro, mas o Linux e outras versões apenas emitem um aviso. Isso precisa ser corrigido. WTF?

Veja também uma tentativa de corrigir isso como bug # 19498 no MySQL Bugtracker:

Bryce Nesbitt em 4 de abril de 2008 16:36:
No MS Windows, a regra "no DEFAULT" é um erro, enquanto em outras plataformas geralmente é um aviso. Embora não seja um bug, é possível ficar preso a isso se você escrever código em uma plataforma branda e depois executá-lo em uma plataforma estrita:

Pessoalmente, vejo isso como um bug. A pesquisa por "coluna BLOB / TEXT não pode ter um valor padrão" retorna cerca de 2.940 resultados no Google. A maioria deles são relatórios de incompatibilidades ao tentar instalar scripts de banco de dados que funcionavam em um sistema, mas não em outros.

Estou enfrentando o mesmo problema agora em um aplicativo da web que estou modificando para um dos meus clientes, originalmente implantado no Linux MySQL v5.0.83-log. Estou executando o Windows MySQL v5.1.41. Mesmo tentando usar a versão mais recente do phpMyAdmin para extrair o banco de dados, ele não informa um padrão para a coluna de texto em questão. No entanto, quando tento executar uma inserção no Windows (que funciona bem na implantação do Linux), recebo um erro sem padrão na coluna ABC. Tento recriar a tabela localmente com o padrão óbvio (com base em uma seleção de valores exclusivos para essa coluna) e acabo recebendo a coluna BLOB / TEXT tão útil que não pode ter um valor padrão .

Novamente, não manter a compatibilidade básica entre plataformas é inaceitável e é um bug.


Como desativar o modo estrito no MySQL 5 (Windows):

  • Edite /my.ini e procure a linha

    sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
  • Substitua por

    sql_mode='MYSQL40'
  • Reinicie o serviço MySQL (assumindo que seja mysql5)

    net stop mysql5
    net start mysql5

Se você tiver acesso root / admin, poderá executar

mysql_query("SET @@global.sql_mode='MYSQL40'");
Ku Logix
fonte
3
Se você tiver acesso root e estiver usando o phpMyAdmin, vá para a página principal (clique no logotipo phpMyAdmin), vá para a guia Variáveis, localize a variável sql_mode e clique em Editar.
Gavin
1
Estou no CentOS 5.8 e o MySQL v 14.14 Distrib 5.1.71 lança um erro em vez de um aviso ao tentar definir um valor padrão para um campo TEXT. Só gostaria de notar que não está funcionando em todas as plataformas Linux.
30714 Alex
O OS X pelo menos parece lançar um erro nos dias de hoje. Os documentos dev.mysql.com/doc/refman/5.7/en/blob.html dizem "As colunas BLOB e TEXT não podem ter valores PADRÃO". FWIW (mas não por isso)
rogerdpack
31

Sem nenhum conhecimento profundo do mecanismo mySQL, eu diria que isso soa como uma estratégia de economia de memória. Presumo que o motivo esteja por trás deste parágrafo nos documentos :

Cada valor BLOB ou TEXT é representado internamente por um objeto alocado separadamente. Isso contrasta com todos os outros tipos de dados, para os quais o armazenamento é alocado uma vez por coluna quando a tabela é aberta.

Parece que o pré-preenchimento desses tipos de coluna levaria a penalidades de uso e desempenho de memória.

Pekka
fonte
5
-1: o armazenamento de dados, como nomes de cidades, em uma coluna TEXT, na verdade, ocupa menos memória total do que o armazenamento dos mesmos dados em uma coluna CHAR ou VARCHAR.
David Cary
5
@ David O capítulo manual que estou citando não é sobre armazenamento, mas sobre recuperação.
Pekka
1
Não vejo como isso levaria a qualquer uso anormal de memória e penalidades de desempenho. Obviamente, quando um usuário define um valor padrão, ele espera um desempenho atingido, independentemente do tipo de dados (especialmente em operações em massa). No entanto, até onde eu entendo, você afirma que, para um campo BLOB / TEXT, esse impacto no desempenho é relativamente alto em comparação com outros tipos de dados? E como isso está relacionado ao fato de o BLOB / TEXT ser armazenado internamente como um objeto separado? Isso não faz nenhum sentido para mim.
Freakish 21/05
27
IMHO não é uma estratégia de economia de memória. É um bug ou as pessoas que o escreveram são loucas. E acho que é o último, já que eles não podem consertar isso há pelo menos 8 anos. A funcionalidade básica que qualquer outro banco de dados possui.
Freakish
2
Não importa, ainda deve ser uma opção para quem deseja usá-lo.
jurchiks
15

Você pode obter o mesmo efeito que um valor padrão usando um gatilho

create table my_text

(
   abc text
);

delimiter //
create trigger mytext_trigger before insert on my_text
for each row
begin
   if (NEW.abc is null ) then
      set NEW.abc = 'default text';
   end if;
end
//
delimiter ;
Tim Child
fonte
14

Como a questão principal:

Alguém sabe por que isso não é permitido?

ainda não foi respondido, fiz uma pesquisa rápida e encontrei uma adição relativamente nova de um desenvolvedor MySQL no MySQL Bugs :

[17 de março de 2017 15:11] Ståle Deraas

Postado por desenvolvedor:

Esta é realmente uma solicitação de recurso válida e, à primeira vista, pode parecer trivial adicionar. Mas os valores TEXT / BLOBS não são armazenados diretamente no buffer de registro usado para ler / atualizar tabelas. Portanto, é um pouco mais complexo atribuir valores padrão a eles.

Esta não é uma resposta definitiva, mas pelo menos um ponto de partida para o porquê pergunta que.

Enquanto isso, vou apenas codificá-lo e tornar a coluna anulável ou atribuir explicitamente um ''valor (padrão ) para cada um insertdo código do aplicativo ...

Marten Koetsier
fonte
13

"Suporte para DEFAULT em colunas TEXT / BLOB" é uma solicitação de recurso no MySQL Bugtracker (Bug # 21532) .

Vejo que não sou o único que gostaria de colocar um valor padrão em uma coluna TEXT. Eu acho que esse recurso deve ser suportado em uma versão posterior do MySQL.

Isso não pode ser corrigido na versão 5.0 do MySQL, porque aparentemente causaria incompatibilidade e dataloss se alguém tentasse transferir um banco de dados entre os bancos de dados (atuais) que não suportam esse recurso e os bancos de dados que suportam esse recurso.

David Cary
fonte
Parece-me que você deve poder alterá-lo entre "" e NULL para uma coluna TEXT que permita nulo. Não parece possível.
Phpuru Apr
6

Normalmente, executo sites no Linux, mas também desenvolvo em uma máquina Windows local. Eu já tive esse problema várias vezes e apenas consertei as tabelas quando encontrei os problemas. Eu instalei um aplicativo ontem para ajudar alguém e, claro, encontrou o problema novamente. Então, decidi que era hora de descobrir o que estava acontecendo - e encontrei esse tópico. Eu realmente não gosto da idéia de alterar o sql_mode do servidor para um modo anterior (por padrão), então criei uma solução simples (eu acho).

É claro que esta solução exigiria que os desenvolvedores agrupassem seus scripts de criação de tabela para compensar o problema do MySQL em execução no Windows. Você verá conceitos semelhantes nos arquivos de despejo. Uma ressalva BIG é que isso pode / causará problemas se o particionamento for usado.

// Store the current sql_mode
mysql_query("set @orig_mode = @@global.sql_mode");

// Set sql_mode to one that won't trigger errors...
mysql_query('set @@global.sql_mode = "MYSQL40"');

/**
 * Do table creations here...
 */

// Change it back to original sql_mode
mysql_query('set @@global.sql_mode = @orig_mode');

É sobre isso.

Darrell Greenhouse
fonte
1
Isso não aborda a questão de por que o MySQL tem algum comportamento, mas obrigado por compartilhar sua abordagem para que outros possam se beneficiar também. Bem-vindo ao Stack Overflow!
precisa saber é o seguinte
1
Sim, eu sei ... vou ter que olhar mais para o modo STRICT para ver se faz sentido - já que o MySQL lança um aviso nas caixas do Nix, mas falha nas caixas do Windows. Isso é uma indicação de que algo pode estar errado com a implementação, independentemente da plataforma. Você notará que na documentação do MySQL, existe este aviso: "As colunas BLOB e TEXT não podem ter valores PADRÃO". Então, logicamente, parece que a implementação nas versões anteriores a 5 foi realmente interrompida em todas as plataformas.
Darrell Greenhouse
3

Para o Ubuntu 16.04:

Como desativar o modo estrito no MySQL 5.7:

Edite o arquivo /etc/mysql/mysql.conf.d/mysqld.cnf

Se a linha abaixo existir no mysql.cnf

sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

Em seguida, substitua-o por

sql_mode='MYSQL40'

De outra forma

Basta adicionar a linha abaixo no mysqld.cnf

sql_mode='MYSQL40'

Este problema foi resolvido.

Shiv Buyya
fonte