Voltar para a lista de artigos Artigos
6 minutos de leitura

Entendendo o uso do NULL em SQL Lógica com três valores

As NULLs são necessárias em bancos de dados relacionais, e aprender a usá-las é fundamental para o sucesso do SQL. Entretanto, as NULLs também devem ser tratadas com cuidado, como explicamos neste post.

Em bancos de dados relacionais, nem sempre temos um valor a ser colocado em uma coluna. Por exemplo, suponha que tenhamos uma tabela chamada "pessoas" que tenha colunas "primeiro_nome", "último_nome", "data_de_nascimento" e "data_do_casamento". Que valor vamos armazenar na coluna "data_de_casamento" para pessoas solteiras? Nesse caso, a coluna não poderia ter um valor porque as pessoas solteiras não são casadas. Precisamos de uma maneira de indicar que não temos um valor para esta coluna. Felizmente, temos um valor assim: o valor NULL, que é amplamente utilizado em bancos de dados relacionais.

As NULLs podem ser aplicadas a qualquer tipo de dado: inteiros, datas, VARCHARs, ou qualquer outro tipo de coluna. Mas precisamos ter cuidado quando criamos cálculos ou expressões contendo um ou mais operadores com um valor NULL. Vamos ver por quê.

NULLs e Lógica de Três Valores

A razão pela qual os NULLs às vezes podem tropeçar nas pessoas tem a ver com algo chamado lógica de três valores. Enquanto a lógica binária ou booleana tem dois valores ("verdadeiro" e "falso"), a lógica tridimensional (abreviada como 3VL e também conhecida como lógica ternária) tem um valor adicional - "desconhecido".

Vamos ilustrar a 3VL com um cenário simples. Suponhamos que queremos obter os nomes dos funcionários que ganham mais de 1.200 euros por mês. O employee tabela tem este aspecto:

First Name Last Name Salary Bonus
John Smith 1000 500
Mary Smith 1000 1500
Peter White 1800 NULL
Nick Perry 1000 NULL

Tentamos a seguinte pergunta:

SELECT * FROM employee WHERE bonus + salary > 1200;

O resultado é:

First Name Last Name Salary Bonus
John Smith 1000 500
Mary Smith 1000 1500

Devemos ver três registros no conjunto de resultados, mas há apenas dois. Por que Peter White não está incluído? O motivo está relacionado com o valor NULL na coluna bonus. Em SQL, toda operação aritmética que inclui um operando com um valor NULL retorna um resultado NULL.

Então, com isto em mente, veja como o registro de Peter White foi avaliado:

1800 + NULL > 1200

Em outras palavras, o salário de Peter (1.800) e seu bônus (NULL) somados ao NULL. Podemos reduzir esta condição para :

NULL > 1200

Então o NULL é maior que 1.200? Lembre-se que o NULL representa um valor inexistente, o que significa que não temos nada a comparar com 1.200: não podemos saber se esta afirmação é verdadeira ou falsa. É assim que funciona a lógica dos três valores. Quando temos um valor NULL em uma condição, o resultado desta condição será "desconhecido".

Vindo para Grips com 3VL em Consultas SQL

Para entender como funciona a lógica de três valores, vamos passar pelo processo passo a passo. Primeiro, pense em como os registros são filtrados na cláusula WHERE. Somente os registros que avaliam para "verdadeiro" na cláusula WHERE são parte do resultado da consulta definida. Registros que avaliam para "falso" ou "desconhecido" não fazem parte do resultado. Esta é a razão pela qual o registro de Peter White foi deixado de fora dos resultados da consulta anterior. Seu salário total é avaliado como "Desconhecido" na cláusula WHERE; "1800 + NULL > 1200" é "Desconhecido" porque não podemos saber o que é NULL.

E, OU e NÃO tabelas também são importantes na lógica de três valores, portanto, vamos olhar para elas individualmente e ver como elas computam. Vamos começar com a tabela NOT:

Value NOT Result
True False
False True
Unknown Unknown

A seguir, vamos ver a tabela AND:

AND True False Unknown
True True False Unknown
False False False False
Unknown Unknown False Unknown

Vamos analisar por que "falso" E "desconhecido" equivale a "falso". Um "falso" é suficiente para tornar o resultado inteiro "falso" em uma operação AND. Isto é verdadeiro independentemente de o segundo valor ser "verdadeiro", "falso", ou "desconhecido".

Finalmente, temos a tabela OR:

OR True False Unknown
True True True True
False True False Unknown
Unknown True Unknown Unknown

Vamos tentar uma consulta que utiliza o operador OR:

SELECT * FROM employee WHERE salary < 1500 OR bonus > 200 

O resultado é o seguinte:

First Name Last Name Salary Bonus
John Smith 1000 500
Mary Smith 1000 1500
Nick Perry 1000 NULL

Observe que um registro contendo um valor NULL na coluna "bônus" é mostrado no resultado, mas o outro registro NULL não é. O motivo é o operador OR. Como o salário da condição < 1500 é verdadeiro, não é necessário avaliar o bônus da condição > 200.

Como lidar com a Variável Desconhecida

Você pode às vezes evitar o uso de valores "desconhecidos" nas condições WHERE, convertendo valores NULL para outros valores (como 0) usando a função COALESCE(). Considere os exemplos anteriores. Se você convertesse cada NULL em "0" antes de comparar o valor na ONDE, você obteria resultados diferentes dos mostrados acima. Entretanto, esta conversão pode ou não ser possível, dependendo da semântica da consulta. Ainda assim, vamos tentar e ver o que acontece.

SELECT * FROM employee WHERE coalesce(bonus,0) > 200 OR salary < 1500

A consulta gerará apenas resultados "verdadeiros" ou "falsos". Neste caso, será aplicada uma lógica de dois valores.

Suponhamos que recebamos uma ordem para dar um aumento salarial de 5% aos funcionários que ganhem menos de 1.600 euros por mês. Como devemos escrever esta pergunta? Vamos tentar:

UPDATE employee
SET salary = salary *1.05
WHERE salary + bonus <= 1600

Aqui estão os resultados:

First Name Last Name Salary Bonus
John Smith 1050 500
Mary Smith 1000 1500
Peter White 1800 NULL
Nick Perry 1000 NULL

Espere um minuto - o salário do Nick não mudou! Isso não é justo! Novamente, o resultado "desconhecido" da condição "salário + bônus <= 1600" para o registro de Nick está causando um problema.

Nossa segunda tentativa é melhor:

UPDATE employee
SET salary = salary *1.05
WHERE salary + coalesce(bonus,0) <= 1600

Como podemos ver no resultado da consulta seguinte, o salário de ambos os registros (John e Nick) foi modificado.

First Name Last Name Salary Bonus
John Smith 1050 500
Mary Smith 1000 1500
Peter White 1800 NULL
Nick Perry 1050 NULL

Experimente você mesmo!

Pode haver muitas cláusulas diferentes ONDE avaliar para "desconhecido" ou "falso". Por que não tentar algumas consultas SQL e ver quais retornam valores "verdadeiros", "falsos" ou "desconhecidos"? LearnSQL.com.br pode lhe ensinar tudo sobre a cláusula WHERE e suas condições. Experimente de graça!