【问题标题】:PostgreSQL - Check foreign key exists when doing a SELECTPostgreSQL - 执行 SELECT 时检查外键是否存在
【发布时间】:2015-03-19 21:17:40
【问题描述】:

假设我有以下数据:

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_idother_table 到某个名称的列。

在 PostgreSQL 中使用以下查询:

SELECT * 
FROM some_table 
WHERE other_table_id = 3;

如您所见,3 不存在于other_table 这个查询显然会返回 0 个结果。

不进行第二次查询,有没有办法知道我用作过滤器的外键是否在other_table 中不存在?

理想情况下,作为稍后可以解析的错误(例如,当使用错误的外键执行 INSERTUPDATE 时会发生这种情况)。

【问题讨论】:

  • 请编辑您的问题并提供示例数据和所需结果。您的问题的答案是“是”,但您没有说明您需要这些信息的方式。
  • 已编辑,如果需要澄清,请告诉我

标签: sql postgresql foreign-keys


【解决方案1】:

你可以利用 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 来演示这一点。

【讨论】:

    【解决方案2】:

    如果您对some_table 执行INSERTUPDATE,指定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 中选择列),即使是声明为 not空。

    如果您希望此类查询引发错误,那么您可能需要编写一个自定义函数来提供帮助,但这是可以做到的。我可能会在 PL/pgSQL 中使用该语言的 RAISE 语句来实现它。

    【讨论】:

    • 我也会用 plpgsql 来实现它。事实上,我只是这样做了。
    猜你喜欢
    • 1970-01-01
    • 2018-07-26
    • 2019-01-08
    • 2020-01-18
    • 1970-01-01
    • 2021-11-11
    • 2011-11-20
    • 2011-06-10
    • 1970-01-01
    相关资源
    最近更新 更多