在 plpgsql 函数中访问 select 语句结果
Posted
技术标签:
【中文标题】在 plpgsql 函数中访问 select 语句结果【英文标题】:Access select statement result in plpgsql function 【发布时间】: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
【问题讨论】:
【参考方案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。以上是关于在 plpgsql 函数中访问 select 语句结果的主要内容,如果未能解决你的问题,请参考以下文章