Suppose I have the following data:
Table some_table
:
some_table_id | value | other_table_id
--------------------------------------
1 | foo | 1
2 | bar | 2
Table other_table
:
other_table_id | value
----------------------
1 | foo
2 | bar
Here, some_table
has a foreign key to column other_table_id
from other_table
into the column of some name.
With the following query in PostgreSQL:
SELECT *
FROM some_table
WHERE other_table_id = 3;
As you see, 3
does not exists in other_table
This query obviously will return 0 results.
Without doing a second query, is there a way to know if the foreign key that I am using as a filter effectively does not exist in the other_table
?
Ideally as an error that later could be parsed (as it happends when doing an INSERT
or an UPDATE
with a wrong foreign key, for example).
You can exploit a feature of PL/pgSQL to implement this very cheaply:
A final
RETURN;
is optional in this case.The
WARNING
is only raised if your query doesn't return any rows. I am not raising anERROR
in the example, since this would roll back the whole transaction (but you can do that if it fits your needs).We've added a code example to the manual with Postgres 9.3 to demonstrate this.
If you perform an
INSERT
orUPDATE
onsome_table
, specifying another_table_id
value that does not in fact exist inother_table
, then you will get an error arising from violation of the foreign key constraint.SELECT
queries are therefore your primary concern.One way you could address the issue with
SELECT
queries would be to transform your queries to perform an outer join withother_table
, like so:That query will always return at least one row if any
other_table
row hasother_table_id = 3
. In that case, if there is no matchingsome_table
row, then it will return exactly one row, with that row having all columnsNULL
(given that it selects only columns fromsome_table
), even columns that are declared not null.If you want such queries to raise an error then you'll probably need to write a custom function to assist, but it can be done. I'd probably implement it in PL/pgSQL, using that language's
RAISE
statement.