【问题标题】:PL/pgSQL checking if a row existsPL/pgSQL 检查一行是否存在
【发布时间】:2012-08-07 04:46:36
【问题描述】:

我正在 PL/pgSQL 中编写一个函数,我正在寻找检查行是否存在的最简单方法。
现在我正在选择一个integer 到一个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;

【问题讨论】:

    标签: sql postgresql plpgsql postgresql-9.1 exists


    【解决方案1】:

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

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

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

    使用来自 cmets 中 @a_horse_with_no_name 的输入进行了改进。

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

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

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

    【讨论】:

    • 好点! (虽然 person_id 可能是主键,所以它只会使用索引查找“扫描”单个表)。
    • A count(*) 有条件(特别是不在 PK 列上)将触发顺序扫描。
    • @a_horse_with_no_name:你当然是对的!我正在考虑一个简单的计数 - 正如您在评论中的示例中所看到的那样。我根据您的意见改进了我的答案,谢谢。
    • 如果你想在函数之外使用它,如何做到这一点的语法在这里:stackoverflow.com/a/20957691/908677
    • @EugenKonkov:我在这方面领先:Simpler, shorter, faster.
    【解决方案2】:

    使用计数(*)

    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 或其他东西来测试由其主键标识的行是否存在。它一种有效的测试方法。

    【讨论】:

    • 不要为此使用 COUNT - 这是性能问题 - 或者您必须使用派生表 SELECT COUNT(*) FROM (SELECT * FROM people LIMIT 1) x
    • @PavelStehule:即使 主键上有where 条件?我无法想象这可能会比你的陈述慢得多。两种解决方案的执行计划几乎相同。
    • @a_horse_with_no_name 当它过滤到 PK 时,99% 就可以了。在这种情况下,PL/pgSQL 应该评估 2 个 SELECT 而不是一个。但这种模式是有风险的。有些人不做验证所以过滤是为了PK
    • @PavelStehule:我为此添加了解释。我比较了 Erwin 和我的解决方案的计划,没有(真正的)差异。由于索引列上有where,这高效的。
    • @a_horse_with_no_name,确切地说——它是“微不足道的”SELECT(比普通 SELECT 快大约 10 倍),但它仍然是 SELECT。如果您想查看 plpgsql 代码的真实面貌,请使用#option dump -- 请参阅文章postgres.cz/wiki/PL/pgSQL_efektivn%C4%9B 中的第一个代码列表(对不起,文章是捷克语,但示例是英文)-translate.google.com/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-24
    • 1970-01-01
    • 1970-01-01
    • 2012-11-09
    • 2012-03-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多