Esse artigo faz parte da revista Clube Delphi edição 7. Clique aqui para ler todos os artigos desta edição


Atenção: por essa edição ser muito antiga não há arquivo PDF para download. Os artigos dessa edição estão disponíveis somente através do formato HTML. 

Banco de Dados: Ser ou Não Ser NULL

 

Como primeira matéria sobre banco de dados, falaremos um pouco sobre o NULL. O conceito envolvido no NULL serve para qualquer banco de dados. Uma coluna com NULL é considerada desconhecida. O NULL segue a lógica dos três estados, que pode ser avaliada como: True, False ou desconhecido. Antes de se permitir NULL e trabalhar com ele em uma coluna, deve-se aplicar esta lógica para não obtermos resultados inconsistentes.

Imaginemos uma tabela de nome CLIENTES com as colunas: IDCliente, NomeCliente, Estado. Permitiremos NULL na coluna Estado:

 

Create Table CLIENTES

(

IDCliente int Primary Key,

NomeCliente Char(50) NOT NULL,

Estado Char(20) NULL

)

Insert CLIENTES (IDCliente, NomeCliente, Estado)

values (1,’João’, ‘RJ’)

Insert CLIENTES (IDCliente, NomeCliente, Estado)

values (2, ‘Jose’, ‘SP’)

Insert CLIENTES (IDCliente, NomeCliente)

values (3, ‘Maria’)

 

A saída de um simples SELECT * from CLIENTES seria:

 

IDCliente NomeCliente Estado

--------   --------   --------

1                    João                   RJ

2                    José                   SP

3                   Maria                   NULL

 

Imaginemos uma outra consulta: Select * from CLIENTES where Estado <> ‘RJ’

 

O retorno seria apenas uma linha a de:

 

IDCliente NomeCliente Estado

--------   --------   -------

2                    José       SP

 

Para obtermos todas que não possuem RJ teríamos que usar por exemplo a seguinte “query”:

 

Select * from CLIENTES Where Estado <> ‘RJ’ or Estado IS NULL, retornando as duas linhas José SP e Maria NULL.

Temos que ter em mente que desconhecido não é igual, diferente, maior ou menor que um valor qualquer, simplesmente é desconhecido.

Uma consulta: Select * from CLIENTES Where Estado = NULL ou Select * from CLIENTES Where Estado = ‘NULL’ não retornaria linha alguma. Para tais situações devemos usar os operadores IS NULL ou IS NOT NULL no MS-SQL Server.

O NULL permite uma flexibilidade muito grande, mas devemos diminuir o seu uso, já que as aplicações podem estar rodando perfeitamente até que uma bomba relógio estoure e os erros ocorram. Ou mesmo o usuário final, que avaliará o resultado NULL, deve ser capaz de entender o significado deste, o que nem sempre ocorre.

Podemos usar valores fictícios em uma coluna, caso não se inclua um valor na inserção. Para tal, criamos um Default, ou até mesmo, na hora de inserir o registro colocamos o valor fictício. Exemplo:

 

Insert into CLIENTES (IDCliente,

NomeCliente, Estado) values

(3, ‘Maria’, ‘Não informado’)

 

No caso de valores fictícios, temos que ter cuidado ao avaliarmos valores, por exemplo, numéricos. Suponhamos que a coluna Idade fosse acrescentada à tabela CLIENTES, e um valor Default igual a 0 (zero) fosse colocado como fictício para situações onde não sabemos a idade do cliente.

 

Resolveríamos o problema do NULL, mas se calculássemos os valores mínimos ou a média das idades teríamos que desconsiderar a Idade com zero para não obtermos valores irreais.

 

Para situações cuja entrada fictícia pode causar mais problemas que soluções, temos ainda a função ISNULL(expressão, valor substituto). No exemplo dos Estados do Cliente podemos substituir a “query”:

 

(Select * from CLIENTES

Where Estado <> ‘RJ’

Or Estado IS NULL)

 

Pela:

 

(Select * from CLIENTES

Where ISNULL(Estado, ‘XX’)

<> ‘RJ’

 

 

 

 

Vale lembrar que o ANSI SQL não permite a seguinte “query”:

 

(Select * from CLIENTES

Where Estado = NULL)

 

mas permite a “query”:

 

(Update CLIENTES

set Estado = NULL

Where IDCliente = 4)

 

o que pode parecer um pouco estranho ou sem coerência.

 

 

 

Temos ainda a opção de modificarmos a avaliação do NULL, ou seja, podemos fazer uma expressão ser avaliada True ou False com (=NULL). No SQL Server podemos alterar esta lógica usando a opção SET ANSI_NULLS{ON | OFF}. Se rodarmos SET ANSI_NULLS ON valerá tudo que falamos acima, logo a “query” Select * from CLIENTES Where Estado = NULL não retornará nada. Se pusermos SET ANSI_NULLS OFF a “query” retornará as linhas que contiverem a coluna Estado com NULL.

É recomendável, no SQL Server, definir SET ANSI NULLS ON e utilizar o operador IS NULL. Tenha sempre em mente a lógica dos três estados que não haverá problema.

Ao criarmos ou alterarmos uma tabela, podemos declarar a permissividade do NULL ou NOT NULL explicitamente. No exemplo CREATE TABLE da tabela CLIENTES, colocamos NOT NULL e NULL para as colunas, pois este procedimento é recomendável para não haver dúvidas. Se estivermos com a opção SET ANSI_DEFAULTS como ON, a opção SET ANSI_NULL_DFLT_ON estará em ON. Logo, se não declaramos explicitamente a palavra NULL como padrão, o SQL Server permitirá o NULL na coluna.

Podemos em tempo de execução alterar o padrão com SET ANSI_NULL_DFLT_ON{ON|OFF}.

 

Para o padrão ANSI SQL, se nada for especificado, deve ser considerado NULL como permitido, mas procure sempre declarar explicitamente o NULL ou NOT NULL, assim não restará dúvidas quanto ao padrão.

Outra característica em relação ao NULL é que as colunas de uma chave primária devem ser declaradas explicitamente ou implicitamente como NOT NULL, o que é muito coerente. Já uma chave Unique permite um e só um valor da(s) coluna(s) com NULL o que é permitido, mas não muito útil. Portanto, não devemos usar o NULL nestes casos.

Para terminar, devemos evitar o uso de NULL, pois poderemos ter resultados não esperados ou o usuário final pode não entender o significado do NULL. Claro que num primeiro momento ao permitir NULL estaremos resolvendo situações cuja a análise e o respectivo modelo de dados não foram bem discutidos, mas se “perdermos” um tempo nesta etapa, evitaremos problemas futuros e, conseqüentemente, diminuiremos o custo de manutenção do banco e aplicativo.

Como exercício achem qual das consultas retornarão 9, com duas hipóteses, uma com SET ANSI_NULLS ON e outra com SET ANSI_NULLS OFF:

 

TABELA:

 

X Y

(null) 1

 

Select 9 from TABELA where X <> Y

Select 9 from TABELA where X = Y

Select 9 from TABELA where X != Y

Select 9 from TABELA where X < Y

Select 9 from TABELA where X !< Y

Select 9 from TABELA where X > Y

Select 9 from TABELA where X !> Y

Select 9 from TABELA where X is NULL

Select 9 from TABELA where X = NULL