【问题标题】:Access select statement result in plpgsql function在 plpgsql 函数中访问 select 语句结果
【发布时间】:2021-04-11 09:07:48
【问题描述】:

如何在 plpgsql 函数中访问 select 语句的结果以检查其内容?

我需要检查我使用的ilike 函数是否在我的people 表中返回任何匹配的演员。如果没有匹配项,我需要在“actor_details”表中返回“No matching name”,但如果有多个不同的值,我需要返回“Non-distinct actor name”之类的内容。

如果其中任何一个条件为真,我需要跳出函数并简单地在“actor_details”表中返回这些文本字符串。

在我的实际函数中,我需要在该语句之后附加几行文本,因此RETURNS table

任何指针都会很棒。最后两行代码中定义的预期输出。

CREATE TABLE people (
    id integer NOT NULL,
    name text NOT NULL,
    year_born integer,
    year_died integer
);

insert into people (id, name, year_born, year_died) values
(20000007,  'Humphrey Bogart',  1899,   1957)
(20000008,  'Marlon Brando',    1924,   2004)
(20000009,  'Richard Burton',   1925,   1984)
(200000010, 'Richard Hunt',     1985,   NULL)

CREATE OR REPLACE FUNCTION actor_details(_pattern text) 
RETURNS table (actor_details text) 
AS $$

BEGIN
  select distinct concat(people.name, ' (', people.year_born, '-', people.year_died, ')') 
    into actor_details
  from people
  where people.name ilike('%' || _pattern || '%');
  
  --- THIS IS WHERE I NEED HELP
  IF (@@ROWCOUNT = 0) then
    select 'No matching name' into actor_details;
  ELSIF (@@ROWCOUNT > 1) then
    select 'Non-distinct actor name';
  END IF; 
  return;              


END
$$ 
LANGUAGE plpgsql;

select * from actor_details('xxyyzz'); ---<<< Should return 'No matching name' in a column titled actor_details
select * from actor_details('Richarch'); ---<<< Should return 'Non-distinct actor name' in a column titled actor_details

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    我建议在查询中进行聚合以获取 actor_details:

    select (case when count(*) = 0
                 then 'No matching name'
                 when count(distinct concat(p.name, ' (', p.year_born, '-', p.year_died, ')')) > 1
                 then 'Non-distinct actor name'
                 else max(concat(p.name, ' (', p.year_born, '-', p.year_died, ')'))
            end)
    into actor_details
    from people p
    where p.name ilike('%' || _pattern || '%');
    

    那么查询之后就不需要任何额外的逻辑了。

    【讨论】:

    • 当我 i) 替换 _pattern 变量的演员名称并自行运行查询或 ii) 在函数中使用建议时,我收到错误消息“在“then”处或附近出现语法错误本身。我该如何解决?
    • @dominiquealpinski 。 . .这只是 when 子句中缺少的结束括号。
    【解决方案2】:

    您可以使用UNION ALL 和三个根据匹配数选择字符串的查询来做到这一点。你甚至不需要 PL/pgSQL。 (你想要一个只包含一个值的集合似乎很奇怪。简单地返回一个标量可能更有意义。)

    CREATE
     OR REPLACE FUNCTION actor_details
                         (_pattern text) 
                         RETURNS table
                                 (actor_details text) 
    AS
    $$
    SELECT concat(people.name,
                  ' (',
                  people.year_born,
                  '-',
                  people.year_died,
                  ')')
           FROM people
           WHERE people.name ILIKE '%' || _pattern || '%'
                 AND (SELECT count(*)
                             FROM people
                             WHERE people.name ILIKE '%' || _pattern || '%') = 1
    UNION ALL
    SELECT 'No matching name'
           WHERE (SELECT count(*)
                         FROM people
                         WHERE people.name ILIKE '%' || _pattern || '%') = 0
    UNION ALL
    SELECT 'Non-distinct actor name'
           WHERE (SELECT count(*)
                         FROM people
                         WHERE people.name ILIKE '%' || _pattern || '%') > 1;
    $$ 
    LANGUAGE sql;
    

    db<>fiddle

    【讨论】:

    • 是否可以保留我在上面示例中使用的格式?我问是因为在此操作完成后,我需要将每个演员所在的电影列表附加到表“actor_details”中。使用建议的答案会产生一个函数,该函数返回表中的电影列表,但不返回演员姓名(或出生/死亡年份)。
    • 似乎提出的问题有几个令人满意的答案。你应该接受其中之一。如果您现在还需要从另一个表中获取数据,那么您需要提出另一个问题。 提示这将涉及一个Join。
    猜你喜欢
    • 1970-01-01
    • 2014-05-02
    • 1970-01-01
    • 2013-10-18
    • 2013-02-20
    • 1970-01-01
    • 2012-12-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多