Using a plpgsql procedure to extract a record if it exists, and then if it does, do something with it.
The variable is a rowtype:
my_var my_table%rowtype;
I populate it with a SQL statement:
select * from my_table where owner_id = 6 into my_var;
I know it definitely has the row:
raise notice 'my_var is %', my_var;
Returns:
NOTICE: my_var is (383,6,10)
But now I want to test that it got the record and BOTH of these if conditions fail:
if my_var is null then
raise notice 'IT IS NULL';
end if;
if my_var is not null then
raise notice 'IT IS NOT NULL';
end if;
Neither of these raises appear in my messages log - it just never enters the blocks. What's the correct way to test if you received a row from a SELECT * INTO
?
I see two possible reasons, why ...
Not logged
Firstly, a
NOTICE
is not normally written to the database log with default settings. I quote the manual here:Bold emphasis mine. Also note the different default (
NOTICE
) forclient_min_messages
(previous item in the manual).Invalid test
Secondly, consider how a row expression is evaluated. A test
row_variable IS NULL
returnsTRUE
if (and only if) every single element isNULL
. Given the following example:Both expressions return
FALSE
. In other words, a row (or record) variable(1, NULL)
is neitherNULL
, nor is itNOT NULL
. Therefore, both of your tests fail.-> SQLfiddle with more details.
More details, explanation, links and a possible application for this behavior in a
CHECK
constraint in this related answer:NOT NULL constraint over a set of columns
You can even assign a record variable with NULL (
rec := NULL
), which results in every element being NULL - if the type is a well-known row type. Otherwise, we are dealing with an anonymous record and the structure is undefined and you cannot access elements to begin with. But that's not the case with arowtype
like in your example (which is always well-known).Solution:
FOUND
You have to consider that the row could be NULL, even if it was assigned. The query could very well have returned a bunch of NULL values (if the table definition in your query allows NULL values). Such a test would be unreliable by design.
There is a simple and secure approach. Use
GET DIAGNOSTICS ...
or (where applicable) the special variableFOUND
:Details in the manual.