MySQL, melhor inserir string NULL ou vazia?


230

Eu tenho um formulário em um site que possui vários campos diferentes. Alguns dos campos são opcionais, enquanto outros são obrigatórios. No meu banco de dados, tenho uma tabela que contém todos esses valores. É melhor inserir um valor NULL ou uma string vazia nas colunas do banco de dados em que o usuário não colocou nenhum dado?

Respostas:


220

Ao usar, NULLvocê pode distinguir entre "não colocar dados" e "colocar dados vazios".

Mais algumas diferenças:

  • A LENGTHde NULLé NULL, a LENGTHde uma cadeia vazia é 0.

  • NULLs são classificados antes das cadeias vazias.

  • COUNT(message)contará cadeias vazias, mas não NULLs

  • Você pode procurar uma sequência vazia usando uma variável vinculada, mas não a NULL. Esta consulta:

    SELECT  *
    FROM    mytable 
    WHERE   mytext = ?

    nunca corresponderá a NULLin mytext, qualquer que seja o valor que você passar do cliente. Para combinar NULLs, você precisará usar outra consulta:

    SELECT  *
    FROM    mytable 
    WHERE   mytext IS NULL

3
mas qual você acha que é mais rápido? 0 ou NULL ou ""
Atul Dravid

8
no InnoDB NULL ocupam menos espaço
Timo Huovinen

37
Acho que essa é uma resposta correta, mas também ignora totalmente o elemento "melhor prática" da pergunta e se concentra apenas em fatos tangencialmente relevantes (ordem de classificação e comprimento NULL? Isso não importa). Na maioria dos tipos de entrada de dados de texto, não há diferença entre "sem resposta" e "resposta vazia"; portanto, acho que essa é uma ótima pergunta que merece uma resposta melhor.
Nick

6
NULLs também funcionam muito bem quando o campo UNIQUE está definido. Por exemplo, se você tem um campo como Carta de Condução para adicionar o DL da pessoa e o cara não o possui. Como é um campo exclusivo, a primeira pessoa sem número de DL será adicionada, mas não a próxima, pois gerará um erro de restrição exclusiva. Então, NULL é melhor.
Saifur Rahman Mohsin

1
@ Quassnoi ah desculpe ... eu quis dizer, por que é uma má prática definir a carteira de motorista como única ...?
cedbeu

44

Uma coisa a considerar, se você está pensando em mudar bases de dados, é que a Oracle não suporta cadeias vazias . Eles são convertidos para NULL automaticamente e você não pode consultá-los usando cláusulas como WHERE somefield = ''.


11
Isso me pareceu incrivelmente suspeito, mesmo no seu link, então eu tentei. Campo nulo, definido como '', o oracle o ignora. Relatórios comprimento como nulo em vez de 0. Isso é tão errado. Tem que haver alguma maneira de contornar isso. Acho que vou postar isso como outra pergunta.
Steve B.

1
Steve B.: veja esta pergunta: stackoverflow.com/questions/1171196/…
Quassnoi

Obrigado pela referência, embora ainda não entenda o raciocínio. Postado em stackoverflow.com/questions/1268177/…
Steve B.

Pode valer a pena atualizar a resposta para incluir informações a partir do link postado por Quassnoi
SamuelKDavis

7
A Peoplesoft (com Oracle DB) usa um único espaço para indicar um valor vazio. Incrivelmente estúpido. Eles também usam 0,00025 para indicar 0 para FTE, pois 0 não é permitido. Foram feitas escolhas encantadoras nesse produto.
JP Duffy

9

Uma coisa a ter em mente é que NULL pode tornar seus caminhos de código muito mais difíceis. No Python, por exemplo, a maioria dos adaptadores de banco de dados / ORMs é mapeada NULLpara None.

Então, coisas como:

print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow

pode resultar em "Olá, nenhum Joe Doe!" Para evitá-lo, você precisa de algo como este código:

if databaserow.title:
    print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow
else:
    print "Hello, %(firstname) %(lastname)!" % databaserow

O que pode tornar as coisas muito mais complexas.


25
Na minha opinião, abusar do seu banco de dados para "corrigir" erros no seu código ou na estrutura é uma prática (muito) ruim de codificação. Quando não houver dados, você deve apenas inserir NULL e ser consistente ao usá-los. Caso contrário, você deve usar instruções como: if (myString == null || myString = ""). Quando um objeto não está definido ou definido no seu código, você também está usando NULL em vez de algum tipo de "espaço reservado" (que é uma string vazia na minha opinião).
Gertjan

5
Depende muito do seu idioma de escolha. Em Python "se não for myString:" testa Nenhum e "". Provavelmente principalmente questões culturais. A "má prática" do Java Guys é a elegância da pessoa dinâmica.
max

9

Melhor inserir NULLpara consistência no seu banco de dados no MySQL. Chaves estrangeiras podem ser armazenadas como, NULLmas NÃO, como cadeias vazias.

Você terá problemas com uma string vazia nas restrições. Pode ser necessário inserir um registro falso com uma string vazia exclusiva para satisfazer uma restrição de Chave Estrangeira. Má prática, eu acho.

Consulte também: Uma chave estrangeira pode ser NULL e / ou duplicada?


A questão das restrições me tropeçou no passado, e é por isso que eu "+1" a esta resposta.
HPWD

Mas se você usar NULL, tenha certeza de que nunca acabará com nenhuma string vazia. Fácil de fazer com muitas tecnologias de interface do usuário.
Tuntable

5

Não sei qual seria a melhor prática aqui, mas geralmente erro em favor do nulo, a menos que você queira que nulo signifique algo diferente de cadeia vazia, e a entrada do usuário corresponde à sua definição de cadeia vazia.

Observe que estou dizendo que você precisa definir como deseja que sejam diferentes. Às vezes faz sentido tê-los diferentes, às vezes não. Caso contrário, basta escolher um e ficar com ele. Como eu disse, tendem a favorecer o NULL na maioria das vezes.

Ah, e lembre-se de que, se a coluna for nula, é menos provável que o registro apareça em praticamente qualquer consulta que seleciona (possui uma cláusula where, em termos de SQL) baseada nessa coluna, a menos que a seleção seja para uma coluna nula claro.


1
... E agora que vejo a resposta acima de mim, acho seguro dizer que a diferenciação usual com a qual você se preocuparia seria sem dados versus dados vazios. :-)
Platinum Azure

1

Se você estiver usando várias colunas em um índice exclusivo e pelo menos uma dessas colunas for obrigatória (ou seja, um campo de formulário obrigatório), se você definir as outras colunas no índice como NULL, poderá terminar com linhas duplicadas. Isso ocorre porque os valores NULL são ignorados em colunas exclusivas. Nesse caso, use cadeias de caracteres vazias nas outras colunas do índice exclusivo para evitar linhas duplicadas.

COLUNAS EM ÍNDICE ÚNICO:
(event_type_id, event_title, data, local, URL)

EXEMPLO 1:
(1, 'Churrasco', '27/07/2018', nulo, nulo)
(1, 'BBQ', '2018-07-27', null, null) // permitido e duplicado.

EXEMPLO 2:
(1, 'Churrasco', '2018-07-27', '', '')
(1, 'BBQ', '2018-07-27', '', '') // NÃO é permitido porque está duplicado.

Aqui estão alguns códigos:

CREATE TABLE `test` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `event_id` int(11) DEFAULT NULL,
  `event_title` varchar(50) DEFAULT NULL,
  `date` date DEFAULT NULL,
  `location` varchar(50) DEFAULT NULL,
  `url` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `event_id` (`event_id`,`event_title`,`date`,`location`,`url`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

Agora insira isso para ver se isso permitirá as linhas duplicadas:

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);

Agora insira isso e verifique se não é permitido:

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');

Portanto, não há certo ou errado aqui. Cabe a você decidir o que funciona melhor com suas regras de negócios.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.