假设我有以下数据:
表some_table
:
some_table_id | value | other_table_id
--------------------------------------
1 | foo | 1
2 | bar | 2
表other_table
:
other_table_id | value
----------------------
1 | foo
2 | bar
此处,some_table
有other_table_id
列other_table
的外键到某个名称的列。
在PostgreSQL中使用以下查询:
SELECT *
FROM some_table
WHERE other_table_id = 3;
如您所见,3
中不存在other_table
此查询显然会返回0结果。
不进行第二次查询,是否有办法知道other_table
中是否存在我作为过滤器有效使用的外键?
理想情况下,作为以后可以解析的错误(例如,在使用错误的外键执行INSERT
或UPDATE
时发生的错误)。
答案 0 :(得分:4)
您可以利用PL / pgSQL的功能实现 非常便宜 :
CREATE OR REPLACE FUNCTION f_select_from_some_tbl(int)
RETURNS SETOF some_table AS
$func$
BEGIN
RETURN QUERY
SELECT *
FROM some_table
WHERE other_table_id = $1;
IF NOT FOUND THEN
RAISE WARNING 'Call with non-existing other_table_id >>%<<', $1;
END IF;
END
$func$ LANGUAGE plpgsql;
在这种情况下,最终RETURN;
是可选的。
仅当您的查询未返回任何行时才会引发WARNING
。我没有在示例中提出ERROR
,因为这会回滚整个事务(但如果符合您的需要,您可以这样做)。
我们添加了一个代码示例to the manual with Postgres 9.3来证明这一点。
答案 1 :(得分:2)
如果您在INSERT
上执行UPDATE
或some_table
,请指定other_table_id
中实际上不存在的other_table
值,那么您将获得违反外键约束引起的错误。因此,SELECT
查询是您最关心的问题。
使用SELECT
查询解决问题的一种方法是将查询转换为使用other_table
执行外部联接,如下所示:
SELECT st.*
FROM
other_table ot
LEFT JOIN some_table st ON st.other_table_id = ot.other_table_id
WHERE st.other_table_id = 3;
如果other_table
行有other_table_id = 3
,那么该查询将始终返回至少一行。在这种情况下,如果没有匹配的some_table
行,那么它将只返回一行,该行包含所有列NULL
(假设它只选择some_table
中的列),甚至声明为非空的列。
如果您希望此类查询引发错误,那么您可能需要编写自定义函数来协助,但可以完成。我可能会使用该语言的RAISE
语句在PL / pgSQL中实现它。