(relativamente novo em SQL e SQL Server) Estou lendo SQL Server 2012 T-SQL Fundamentals de Itzik Ben-Gan. Autor afirma que:
SQL tem diferentes tratamentos para UNKNOWN em diferentes elementos de linguagem
Então, eu examinei a documentação do SQL Server, e em particular a WHERE
cláusula , mas não consegui encontrar nada específico sobre como NULL/UNKNOWN
é tratado.
Alguém poderia me indicar o documento correto ou indicar o que estou lendo de errado na documentação? (Suspeito muito que a resposta à minha pergunta esteja enterrada em algum lugar do padrão SQL, mas pode ser muito complexa para mim, pelo menos neste momento.)
Existem diferenças sutis sobre como
UNKNOWN
eNULL
são tratados nas várias cláusulas.Três cláusulas em que uma expressão booleana pode aparecer são
WHERE
,HAVING
eFROM
(naON
subcláusula). Em todos os três, oUNKNOWN
é tratado da mesma maneira.WHERE <boolean expression>
:uma linha "passa" pelo
<boolean expression>
e é retornada se a expressão for avaliada comoTRUE
. Se a expressão for avaliada comoFALSE
ouUNKNOWN
, a linha não passará e será removida da avaliação posterior da consulta.HAVING <boolean expression>
:As linhas examinadas na
HAVING
cláusula são aquelas criadas pela agregação daGROUP BY
cláusula anterior. Semelhante a uma linha acima (criada pela agregação) "passa" o<boolean expression>
e é retornado se a expressão for avaliada comoTRUE
. Se a expressão for avaliada comoFALSE
ouUNKNOWN
, a linha não passará e será removida da avaliação posterior da consulta.a JOIN b ON <boolean expression>
:Cada linha de
a
é verificada em cada linha deb
. Se a expressão forTRUE
, a verificação será aprovada e a combinação das duas linhas será válida para o processamento posterior da consulta. SeFALSE
ouUNKNOWN
, então a combinação é rejeitada.Há uma pequena alteração quando a junção é uma junção externa (
LEFT
,RIGHT
ouFULL
), mas não em relação a comoUNKNOWN
é tratada. O que acontece aqui é que se uma linha da tabela à esquerda (em umaLEFT
junção) não corresponder a nenhuma linha da tabela à direita (ou seja, todas as suas verificações são avaliadas comoFALSE
ouUNKNOWN
), essa linha ainda será encaminhada e os valores ausentes para asb
colunas serão preenchidos com nulos.)A situação é diferente nas restrições, há um tratamento mais "relaxado" para
UNKNOWN
. Acho que isso tem a ver com a decisão de permitir nulos em primeiro lugar. Um valor nulo resultará em umUNKNOWN
resultado na maioria das restrições, portanto, faz sentido permitir que essas linhas sejam inseridas. Caso contrário, o efeito seria o mesmo que declarar as colunas comoNOT NULL
.CHECK
restrição:CHECK <expression>
uma linha pode ser inserida (ou atualizada) se a expressão for avaliada como
TRUE
ouUNKNOWN
. Ele é rejeitado apenas se a expressão for avaliada comoFALSE
.FOREIGN KEY
restrição, com colunas anuláveis.semelhante às restrições de verificação, se uma linha tiver um nulo em uma das colunas que participam de uma restrição de chave estrangeira, a verificação da
FOREIGN KEY
restrição é ignorada e a linha pode ser inserida (ou atualizada). restrição de chave estrangeira na tabelaa
:ser equivalente a:
Portanto, se
a.column
forNULL
, a expressão é avaliada comoUNKNOWN
e, portanto, a linha é permitida.UNIQUE
restriçõesAqui, o SQL-Server se desvia do padrão que afirma que, se uma linha com uma restrição exclusiva contiver
NULL
, a verificação exclusiva será ignorada e a linha será permitida.O SQL-Server trata nulos como se fossem valores regulares, quando se trata de restrições únicas e permite apenas um
NULL
valor , em tais colunas.NULL
valores também têm tratamento especial em algumas cláusulas:GROUP BY
:Se uma coluna de agrupamento contiver valores nulos, todos os valores nulos serão considerados iguais e colocados em um único grupo (a mesma coisa acontece em uma
SELECT DISTINCT
consulta).Funções agregadas (
MIN()
,MAX()
,SUM()
eAVG()
outras) ignoram nulos, com exceção deCOUNT()
que podem fazer várias coisas diferentes:COUNT(*)
eCOUNT(constant)
contará todas as linhas.COUNT(column)
eCOUNT(expression)
irá ignorar nulos como as outras funções de agregação e contar apenas linhas onde a coluna ou expressão não é nula.COUNT(DISTINCT column)
eCOUNT(DISTINCT expression)
também irá ignorar nulos e contar apenas as colunas ou expressões não nulas distintas.Portanto, as 4 consultas a seguir podem retornar 4 resultados diferentes se houver nulos na coluna:
ORDER BY
:NULL
valores são tratados como iguais.ASC
e por último quando o pedido éDESC
.(Existe um atributo
NULLS LAST
andNULLS FIRST
definido no padrão mais recente, mas o SQL Server ainda não o implementou.)