O NULL do SQL é estranho
(jirevwe.github.io)-
No SQL, valores
NULLsão tratados de forma peculiar. Uma coluna com restriçãoUNIQUEpode ter vários valoresNULL.- Isso acontece porque cada valor
NULLé considerado um valor independente, diferente dos outrosNULL - SQLite, Postgres e MySQL se comportam assim da mesma forma.
- Isso acontece porque cada valor
-
Definindo a base
select '' = ''; -- Returns 1 (true) strings vazias são iguais select 1 = 1; -- Returns 1 (true) números são iguais select 1 = 0; -- Returns 0 (false) números são diferentes select null = null; -- Returns NULL (null) ué?- Isso acontece porque
NULLé um marcador que representa um "valor desconhecido", então dois valores desconhecidos não são considerados iguais - Usando o operador
IS, é possível verificar a identidade deNULL. Por exemplo,null is nullretorna TRUE.
- Isso acontece porque
-
Sobre unicidade
- Quando uma coluna com restrição
UNIQUEcontém valoresNULL, esses valoresNULLsão considerados distintos entre si e, portanto, não violam a restrição de unicidade. - Por exemplo,
('ray@mail.com', NULL)e('ray@mail.com', NULL)são considerados linhas diferentes.
- Quando uma coluna com restrição
-
Por que o NULL é tratado assim
- O SQLite e outros bancos de dados compatíveis com SQL implementam isso dessa forma para manter consistência com outros bancos. A documentação do padrão SQL sugere que
NULLdeveria ser único em todos os contextos, mas, na prática, a maioria dos motores SQL não trataNULLcomo único emSELECT DISTINCTouUNION.
- O SQLite e outros bancos de dados compatíveis com SQL implementam isso dessa forma para manter consistência com outros bancos. A documentação do padrão SQL sugere que
-
Como garantir unicidade
-
Usando colunas geradas
- É possível mitigar o problema criando uma coluna que sempre tenha um valor determinístico não nulo. Por exemplo, pode-se usar
COALESCE(deleted_at, '1970-01-01')para substituir valoresNULL. - Esse método pode ocupar espaço ao adicionar um campo extra à tabela.
- É possível mitigar o problema criando uma coluna que sempre tenha um valor determinístico não nulo. Por exemplo, pode-se usar
-
Usando índice parcial
- É possível garantir unicidade criando um índice parcial em
emailapenas quandodeleted_atforNULL. - Índices parciais não ampliam a tabela, ocupam menos espaço e não geram erro ao excluir repetidamente o mesmo par de registros.
- É possível garantir unicidade criando um índice parcial em
-
-
Atualização
- O Oracle trata strings vazias como
NULL.
- O Oracle trata strings vazias como
-
Conclusão
- Ao usar ORM isso pode passar despercebido, mas a forma peculiar como o SQL trata
NULLpode causar confusão. A documentação do padrão SQL não é disponibilizada publicamente e só pode ser obtida mediante pagamento.
- Ao usar ORM isso pode passar despercebido, mas a forma peculiar como o SQL trata
2 comentários
Todo
nullé estranho.Por isso, o
nullperfeitamente normal do SQL acaba parecendo o estranho…Em terra de caolho, quem tem dois olhos é anormal…
Comentários do Hacker News
O
NULLdo SQL se baseia na lógica TRUE-FALSE-UNKNOWN de Kleene. Se você lerNULLcomo UNKNOWN, várias operações ficam mais intuitivas de entenderNULLé um marcador que representa UNKNOWN, e não se pode dizer que doisNULLsão iguaisNULLS NOT DISTINCTQuando o conceito de
NULLfoi introduzido nos anos 1970, já se pensava que ele causaria muita confusão no futuro. Passados 45 anos, ele ainda continua sendo debatidoUma forma intuitiva de entender
NULL: o valorNULLem uma célula específica da tabela é uma maneira de representar “sem valor”. Quando você quer valores únicos, casos sem valor não devem ser consideradosCeticismo em relação ao uso de ORM: ORMs são convenientes, mas criaram uma geração que não aprendeu como bancos de dados relacionais realmente funcionam. O comportamento do
NULLem SQL está de acordo com a álgebra relacional básica; o problema é oNULLno estilo CIsso relembra o humor de comparações com
NULLno diálogo de um episódio de BlackadderAcho estranho que, no Oracle,
NULLseja igual a string vaziaEm um contexto orientado a objetos,
nullé útil para indicar que uma determinada propriedade não tem valor. Em JavaScript, hánulleundefined; pode-se supor queundefinedsignifica que o valor é desconhecido, enullsignifica que não há valorNULLnão é estranho no sentido de não haver duplicação. ComoNULLnão é igual a outroNULL, ele não pode ser considerado duplicado. Se você não gosta da semântica deNULL, pode usar um valor sentinelaO
NULLdo SQL não é estranho se você considerar como a lógica relacional deve funcionar em registros que contêm valores inexistentes