Quando usar NULL e quando usar uma string vazia?

82

Estou interessado principalmente no MySQL e PostgreSQL, mas você pode responder o seguinte em geral:

  • Existe um cenário lógico no qual seria útil distinguir uma string vazia de NULL?
  • Quais seriam as implicações do armazenamento físico para armazenar uma cadeia vazia como ...

    • NULO?
    • String vazia?
    • Outro campo?
    • Qualquer outra maneira?
Maniero
fonte

Respostas:

67

Digamos que o registro venha de um formulário para reunir informações de nome e endereço. A linha 2 do endereço normalmente fica em branco se o usuário não morar no apartamento. Uma string vazia neste caso é perfeitamente válida. Costumo preferir usar NULL para significar que o valor é desconhecido ou não é fornecido.

Não acredito que a diferença de armazenamento físico valha a pena se preocupar na prática. Como administradores de banco de dados, temos peixes muito maiores para fritar!

Larry Coleman
fonte
2
+1 muito poucos dba do que nunca precisa se preocupar com as diferenças de velocidade / tamanho do uso NULLou não
Patrick
28
Concordo ... Eu tento reservar NULL para 'desconhecido' ... a string vazia é 'sabemos que deve estar vazia'. É particularmente útil para quando seus dados vierem de várias fontes
Joe
6
Excelente - NULL não é conhecido, String Vazia foi especificada.
precisa saber é o seguinte
@ Larry, qual é o impacto no desempenho? Como o desempenho varia com tabelas de muitas colunas vs. tabelas de muitas linhas?
Shimmy
Concordo que, se houver uma distinção entre nenhum valor fornecido e uma string vazia no seu conjunto de dados, você deverá usá-los adequadamente, mas pessoalmente, se não precisar dessa distinção com meus dados, sempre utilizarei uma string vazia, apenas porque achar que o resultado da consulta de um cliente MySQL na linha de comando pode ser mais limpo para olhar com cadeias vazias em vez de lotes de nulos
RTF
25

Eu não sei sobre MySQL e PostgreSQL, mas deixe-me tratar isso um pouco em geral.

Existe um DBMS, ou seja, o Oracle, que não permite escolher seus usuários entre NULL e ''. Isso demonstra claramente que não é necessário distinguir entre ambos. Existem algumas consequências irritantes:

Você define um varchar2 como uma string vazia como esta:

Update mytable set varchar_col = '';

o seguinte leva ao mesmo resultado

Update mytable set varchar_col = NULL;

Mas, para selecionar as colunas em que o valor está vazio ou NULL, você deve usar

select * from mytable where varchar_col is NULL;

Usando

select * from mytable where varchar_col = '';

está sintaticamente correto, mas nunca retorna uma linha.

Por outro lado, ao concatenar seqüências de caracteres no Oracle. Varchar NULL são tratados como cadeias vazias.

select NULL || 'abc' from DUAL;

produz abc . Outros DBMS retornariam NULL nesses casos.

Quando você deseja expressar explicitamente que um valor é atribuído, é necessário usar algo como ''.

E você precisa se preocupar se o corte não vazio resulta em NULL

select case when ltrim(' ') is null then 'null' else 'not null' end from dual

Faz.

Agora, olhando para o DBMS onde '' não é idêntico ao NULL (por exemplo, SQL-Server)

Trabalhar com '' é geralmente mais fácil e, na maioria dos casos, não há necessidade prática de distinguir entre os dois. Uma das exceções que eu conheço é quando sua coluna representa alguma configuração e você não possui padrões vazios para elas. Quando você pode distinguir entre '' e NULL, é possível expressar que sua configuração está vazia e evitar que o padrão se aplique.

bernd_k
fonte
17

Depende do domínio em que você está trabalhando. NULLsignifica ausência de valor (ou seja, não há valor ), enquanto string vazia significa que existe um valor de string com comprimento zero.

Por exemplo, digamos que você tenha uma tabela para armazenar os dados de uma pessoa e ela contenha uma Gendercoluna. Você pode salvar os valores como 'Masculino' ou 'Feminino'. Se o usuário puder optar por não fornecer os dados de gênero, salve-o como NULL(ou seja, o usuário não forneceu o valor) e não como uma sequência vazia (já que não há gênero com valor '').

Gan
fonte
7
Se o usuário optou por não fornecer um gênero, certamente você deve armazenar "Recusado a fornecer". NULL é ambíguo; também pode significar "o cliente não foi solicitado", "o cliente se identifica com um sexo que não está na nossa lista", etc.
Jon of All Trades
9

É importante lembrar que, quando você tem um campo que não é obrigatório, mas qualquer valor presente deve ser exclusivo, será necessário armazenar valores vazios como NULL. Caso contrário, você poderá ter apenas uma tupla com um valor vazio nesse campo.

Existem também algumas diferenças com álgebra relacional e valores NULL: NULL! = NULL, por exemplo.

Matthew Schinckel
fonte
4
Na verdade, não é o caso que NULL! = NULL, porque é NULL. ;-)
Peter Eisentraut
1
Observe que o MS SQL não segue esta regra: vários valores NULL violam uma UNIQUErestrição. Felizmente, a partir de 2008, você pode usar um índice filtrado para obter um comportamento adequado.
Jon de Todos os Negócios
4

Um novo pensamento, uma grande influência na sua escolha de NULL/ NOT NULLé se você estiver usando uma estrutura. Eu uso muito o symfony e o uso de NULLcampos de permissão simplifica parte da verificação de código e dados ao manipular os dados.

Se você não estiver usando uma estrutura ou se estiver usando instruções e processamento simples de sql, eu escolheria a opção que você achar que é mais simples de acompanhar. Eu geralmente prefiro NULL para que fazer INSERTdeclarações não seja entediante ao esquecer de definir os campos vazios NULL.

Patrick
fonte
a pergunta é sobre NULL vs. string vazia (em uma coluna anulável, IMO), não NULL vs NOT NULL, não é?
Gan
a parte da pergunta perguntando sobre armazenamento me levou a pensar que ele pode estar pensando em Null / não nulo bem
Patrick
ou @ todo mundo sobre a implicação de NULL vs NOT NULL, você pode se referir a isso: dba.stackexchange.com/q/63/107
Gan
2

Tendo trabalhado com a Oracle ( que não permite que você se diferencie ), cheguei à seguinte conclusão:

  • De um ponto de vista lógico, isso não importa. Realmente não consigo pensar em um exemplo convincente em que a diferenciação entre NULL e cadeia de comprimento zero agregue qualquer valor no DBMS.

  • A partir do seguinte: Você possui uma NULLcoluna capaz que não permite zero-len ''(solução Oracle-ish) ou uma NOT NULLcoluna que permite zero-len.

  • E, pela minha experiência, ''faz muito mais sentido ao processar os dados, pois normalmente você gostaria de processar a ausência de uma string como a vazia: concatenação, comparação etc.

Nota: Para voltar à minha experiência com o Oracle: Digamos que você queira gerar uma consulta para uma solicitação de pesquisa. Se você usar, ''poderá gerar WHERE columnX = <searchvalue>e ele funcionará para pesquisas de igualdade. Se você usar, NULLvocê tem que fazer WHERE columnX=<searchvalue> or (columnX is NULL and serchvalue is NULL). Bah! :-)

Martin
fonte
2

Eles também são diferentes da perspectiva do design:

por exemplo

CREATE TABLE t (
    id INTEGER  NOT NULL,
    name CHARACTER(40),
    CONSTRAINT t_PK PRIMARY KEY (id)
);

CREATE UNIQUE INDEX t_AK1 ON t (name);

Parece:

 \d t
          Table "public.t"
 Column |     Type      | Modifiers
--------+---------------+-----------
 id     | integer       | not null
 name   | character(40) |
Indexes:
    "t_pk" PRIMARY KEY, btree (id)
    "t_ak1" UNIQUE, btree (name)

Vamos inserir alguns dados:

op=# insert into t(id, name ) values ( 1, 'Hello');
INSERT 0 1

op=# insert into t( id, name) values ( 2, '');
INSERT 0 1

op=# insert into t( id, name) values ( 3, '');

ERROR:  duplicate key value violates unique constraint "t_ak1"

Agora vamos tentar com null:

op=# insert into t( id, name) values (4, null );

INSERT 0 1

op=# insert into t( id, name) values (5, null);

INSERT 0 1

Isso é permitido.

Soooooo: nulos não são cadeias triviais nem o inverso.

Felicidades

Guy Birkbeck
fonte
1

Se falamos de teoria, as regras do Codd dizem que o RDBMS deve tratar os NULLvalores de uma maneira especial.

Como exatamente isso é usado depende dos arquitetos do banco de dados, dependendo da área real do domínio - tarefa - projeto - aplicação.

noonex
fonte