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ãoDEBUG5,DEBUG4,DEBUG3,DEBUG2,DEBUG1,INFO,NOTICE,NOTICE,ERROR,LOG,FATALePANIC. (...)
O padrão é AVISO . Observe queLOGtem uma classificação diferente aqui do que emclient_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 umSELECT * 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.