PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

O teste IS NOT NULL para um registro não retorna TRUE quando a variável é definida


Eu vejo duas razões possíveis, por que ...

Nenhum desses aumentos aparece no meu log de mensagens

Não registrado


Em primeiro lugar, um NOTICE normalmente não é gravado no log do banco de dados com configurações padrão. Cito o manual aqui:

log_min_messages (enum )

Controla quais níveis de mensagem são gravados no log do servidor. Os valores válidos são DEBUG5 , DEBUG4 , DEBUG3 , DEBUG2 , DEBUG1 , INFO , NOTICE , NOTICE , ERROR , LOG , FATAL e PANIC . (...)
O padrão é AVISO . Observe que LOG tem uma classificação diferente aqui do que em client_min_messages .

Minha ênfase em negrito. Observe também o padrão diferente (NOTICE ) para client_min_messages (item anterior no manual).

Teste inválido


Em segundo lugar, considere como uma expressão de linha é avaliada. Um teste row_variable IS NULL retorna TRUE se (e somente se) todos os elementos é NULL . Dado o seguinte exemplo:
SELECT (1, NULL) IS NULL AS a     -- FALSE
      ,(1, NULL) IS NOT NULL AS b -- also FALSE

Ambos expressões retornam FALSE . Em outras palavras, uma variável de linha (ou registro) (1, NULL) não é NULL , nem é NOT NULL . Portanto, ambos os testes falham.

-> SQLfiddle com mais detalhes.

Mais detalhes, explicação, links e uma possível aplicação para este comportamento em um CHECK restrição nesta resposta relacionada:
NOT NULL constraint sobre um conjunto de colunas

Você pode até atribuir uma variável de registro com NULL (rec := NULL ), o que resulta em cada elemento sendo NULL - se o tipo for um tipo de linha bem conhecido. Caso contrário, estamos lidando com um registro anônimo e a estrutura é indefinida e você não pode acessar os elementos para começar. Mas esse não é o caso de um rowtype como no seu exemplo (que é sempre bem conhecido).

Solução:FOUND


Qual é a maneira correta de testar se você recebeu uma linha de um SELECT * INTO ?

Você deve considerar que a linha pode ser NULL, mesmo que tenha sido atribuída. A consulta pode muito bem ter retornado vários valores NULL (se a definição da tabela em sua consulta permitir valores NULL). Tal teste não seria confiável por design.

Existe uma abordagem simples e segura. Use GET DIAGNOSTICS ... ou (quando aplicável) a variável especial FOUND :
SELECT * FROM my_table WHERE owner_id = 6 INTO my_var;

IF NOT FOUND THEN
   RAISE NOTICE 'Query did not return a row!';
END IF;

Detalhes no manual.