61

我正在 PL/pgSQL 中编写一个函数,并且正在寻找检查行是否存在的最简单方法。
现在我正在 SELECTing an integerinto a boolean,这并没有真正起作用。我对 PL/pgSQL 的经验还不够,还不知道最好的方法。

这是我的功能的一部分:

DECLARE person_exists boolean;
BEGIN

person_exists := FALSE;

SELECT "person_id" INTO person_exists
  FROM "people" p
WHERE p.person_id = my_person_id
LIMIT 1;

IF person_exists THEN
  -- Do something
END IF;

END; $$ LANGUAGE plpgsql;

更新- 我现在正在做这样的事情:

DECLARE person_exists integer;
BEGIN

person_exists := 0;

SELECT count("person_id") INTO person_exists
  FROM "people" p
WHERE p.person_id = my_person_id
LIMIT 1;

IF person_exists < 1 THEN
  -- Do something
END IF;
4

2 回答 2

172

更简单、更短、更快: EXISTS .

IF EXISTS (SELECT 1 FROM people p WHERE p.person_id = my_person_id) THEN
  -- do something
END IF;

查询计划程序可以在找到的第一行处停止 - 而不是count(),它将扫描所有(匹配的)行。与大桌子不同。对于唯一列上的条件,差异很小:只有一行符合条件,并且有一个索引可以快速查找它。

通过评论中@a_horse_with_no_name的输入进行了改进。

您可以只使用一个空SELECT列表:

IF EXISTS (SELECT FROM people p WHERE p.person_id = my_person_id) THEN ...

SELECT列表对 的结果没有影响EXISTS。只有存在至少一个符合条件的行很重要。

于 2012-08-09T22:18:13.633 回答
5

使用计数(*)

declare 
   cnt integer;
begin
  SELECT count(*) INTO cnt
  FROM people
  WHERE person_id = my_person_id;

IF cnt > 0 THEN
  -- Do something
END IF;

编辑(对于没有阅读该声明的反对者和其他可能正在做类似事情的人)

该解决方案之所以有效,是因为列上有一个 where 子句(并且该列的名称表明它是主键 - 所以 where 子句非常有效)

由于该where子句,不需要使用 LIMIT 或其他东西来测试由其主键标识的行的存在。这测试这一点的有效方法。

于 2012-08-09T21:40:12.710 回答